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-2024 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/symmetry_graph.h"
93 #include "scip/dbldblarith.h"
94 
95 
96 #define CONSHDLR_NAME "linear"
97 #define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
98 #define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
99 #define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
100 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
101 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
102 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
103 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
104  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
105 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
106 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
107 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
108 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
110 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
111 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
113 #define EVENTHDLR_NAME "linear"
114 #define EVENTHDLR_DESC "bound change event handler for linear constraints"
116 #define CONFLICTHDLR_NAME "linear"
117 #define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
118 #define CONFLICTHDLR_PRIORITY -1000000
120 #define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
121 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
122 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
123 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
124 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
125 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
126 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
127 #define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
128 #define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
129  * comparison round */
130 #define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
131  * propagation? */
132 #define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
133  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
134 #define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
135  * (0.0: disable constraint aggregation) */
136 #define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
137  * (faster, but numerically less stable) */
138 #define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
139  * to best node's dual bound for separating knapsack cardinality cuts */
140 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
141  * the ones with non-zero dual value? */
142 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
143 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
144 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
145 #define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
146 #define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
147  * constraints using the cheapest variable? */
148 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
149  * function defining an upper bound and prevent these constraints from
150  * entering the LP */
151 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
152  * function defining a lower bound and prevent these constraints from
153  * entering the LP */
154 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
155  * objective function */
156 #define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
157 #define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
158 #define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
159 #define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
160 
161 #define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
162  * removed afterwards? */
163 #define DEFAULT_MAXMULTAGGRQUOT 1e+03 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
164 #define DEFAULT_MAXDUALMULTAGGRQUOT 1e+20 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
165 #define DEFAULT_EXTRACTCLIQUES TRUE /**< should cliques be extracted? */
166 
167 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
168 #define MAXSCALEDCOEF 0 /**< maximal coefficient value after scaling */
169 #define MAXSCALEDCOEFINTEGER 0 /**< maximal coefficient value after scaling if all variables are of integral
170  * type
171  */
172 #define MAXACTVAL 1e+09 /**< maximal absolute value of full and partial activities such that
173  * redundancy-based simplifications are allowed to be applied
174  */
176 #define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
177 #define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
180 #define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of expressions constraints */
181 
182 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
183  * maybe in fullDualPresolve(), see convertLongEquality()
184  */
185 
186 
187 /** constraint data for linear constraints */
188 struct SCIP_ConsData
189 {
190  SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
191  SCIP_Real rhs; /**< right hand side of row */
192  SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
193  SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
194  QUAD_MEMBER(SCIP_Real minactivity); /**< minimal value w.r.t. the variable's local bounds for the constraint's
195  * activity, ignoring the coefficients contributing with infinite value */
196  QUAD_MEMBER(SCIP_Real maxactivity); /**< maximal value w.r.t. the variable's local bounds for the constraint's
197  * activity, ignoring the coefficients contributing with infinite value */
198  SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
199  * over all contributing values */
200  SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
201  * over all contributing values */
202  QUAD_MEMBER(SCIP_Real glbminactivity); /**< minimal value w.r.t. the variable's global bounds for the constraint's
203  * activity, ignoring the coefficients contributing with infinite value */
204  QUAD_MEMBER(SCIP_Real glbmaxactivity); /**< maximal value w.r.t. the variable's global bounds for the constraint's
205  * activity, ignoring the coefficients contributing with infinite value */
206  SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
207  * over all contributing values */
208  SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
209  * over all contributing values */
210  SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
211  SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
212  uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
213  uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
214  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
215  SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */
216  SCIP_VAR** vars; /**< variables of constraint entries */
217  SCIP_Real* vals; /**< coefficients of constraint entries */
218  SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
219  int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
220  int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
221  int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
222  int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
223  int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
224  int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
225  int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
226  int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
227  int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
228  int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
229  int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
230  int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
231  int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
232  int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
233  int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
234  int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
235  int varssize; /**< size of the vars- and vals-arrays */
236  int nvars; /**< number of nonzeros in constraint */
237  int nbinvars; /**< the number of binary variables in the constraint, only valid after
238  * sorting in stage >= SCIP_STAGE_INITSOLVE
239  */
240  unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
241  unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
242  * (0: no, 1: yes, 2: with potentially adding artificial constraint */
243  unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
244  unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
245  unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
246  unsigned int validminact:1; /**< is the local minactivity valid? */
247  unsigned int validmaxact:1; /**< is the local maxactivity valid? */
248  unsigned int validglbminact:1; /**< is the global minactivity valid? */
249  unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
250  unsigned int presolved:1; /**< is constraint already presolved? */
251  unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
252  unsigned int validsignature:1; /**< is the bit signature valid? */
253  unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
254  unsigned int normalized:1; /**< is the constraint in normalized form? */
255  unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
256  unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
257  unsigned int indexsorted:1; /**< are the constraint's variables sorted by type and index? */
258  unsigned int merged:1; /**< are the constraint's equal variables already merged? */
259  unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
260  unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
261  unsigned int coefsorted:1; /**< are variables sorted by type and their absolute activity delta? */
262  unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
263  unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
264  unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
265  unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
266  unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
267 };
268 
269 /** event data for bound change event */
270 struct SCIP_EventData
271 {
272  SCIP_CONS* cons; /**< linear constraint to process the bound change for */
273  int varpos; /**< position of variable in vars array */
274  int filterpos; /**< position of event in variable's event filter */
275 };
276 
277 /** constraint handler data */
278 struct SCIP_ConshdlrData
279 {
280  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
281  SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
282  SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
283  * (0.0: disable constraint aggregation) */
284  SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
285  * to best node's dual bound for separating knapsack cardinality cuts */
286  SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
287  SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
288  * (faster, but numerically less stable) */
289  int linconsupgradessize;/**< size of linconsupgrade array */
290  int nlinconsupgrades; /**< number of linear constraint upgrade methods */
291  int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
292  int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
293  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
294  int maxsepacuts; /**< maximal number of cuts separated per separation round */
295  int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
296  int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
297  int naddconss; /**< number of added constraints */
298  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
299  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
300  SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
301  * the ones with non-zero dual value? */
302  SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
303  SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
304  SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
305  SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
306  SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
307  * constraints using the cheapest variable? */
308  SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
309  SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
310  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
311  SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
312  * function defining an upper bound and prevent these constraints from
313  * entering the LP */
314  SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
315  * function defining a lower bound and prevent these constraints from
316  * entering the LP */
317  SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
318  * the objective function */
319  SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
320  * infeasibility, and extract sub-constraints from ranged rows and
321  * equations */
322  SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
323  int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
324  int rangedrowfreq; /**< frequency for applying ranged row propagation */
325  SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
326  * removed afterwards? */
327  SCIP_Real maxmultaggrquot; /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation */
328  SCIP_Real maxdualmultaggrquot;/**< maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation */
329  SCIP_Bool extractcliques; /**< should cliques be extracted? */
330 };
331 
332 /** linear constraint update method */
333 struct SCIP_LinConsUpgrade
334 {
335  SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
336  int priority; /**< priority of upgrading method */
337  SCIP_Bool active; /**< is upgrading enabled */
338 };
339 
340 
341 /*
342  * Propagation rules
343  */
344 
345 enum Proprule
346 {
347  PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
348  * variable due to the right hand side of the inequality */
349  PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
350  * variable due to the left hand side of the inequality */
351  PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
352  * single variable in this reanged row */
353  PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
354 };
355 typedef enum Proprule PROPRULE;
357 /** inference information */
358 struct InferInfo
359 {
360  union
361  {
362  struct
363  {
364  unsigned int proprule:8; /**< propagation rule that was applied */
365  unsigned int pos:24; /**< variable position, the propagation rule was applied at */
366  } asbits;
367  int asint; /**< inference information as a single int value */
368  } val;
369 };
370 typedef struct InferInfo INFERINFO;
371 
372 /** converts an integer into an inference information */
373 static
375  int i /**< integer to convert */
376  )
377 {
378  INFERINFO inferinfo;
379 
380  inferinfo.val.asint = i;
381 
382  return inferinfo;
383 }
384 
385 /** converts an inference information into an int */
386 static
387 int inferInfoToInt(
388  INFERINFO inferinfo /**< inference information to convert */
389  )
390 {
391  return inferinfo.val.asint;
392 }
394 /** returns the propagation rule stored in the inference information */
395 static
397  INFERINFO inferinfo /**< inference information to convert */
398  )
399 {
400  return (int) inferinfo.val.asbits.proprule;
401 }
402 
403 /** returns the position stored in the inference information */
404 static
405 int inferInfoGetPos(
406  INFERINFO inferinfo /**< inference information to convert */
407  )
408 {
409  return (int) inferinfo.val.asbits.pos;
410 }
411 
412 /** constructs an inference information out of a propagation rule and a position number */
413 static
415  PROPRULE proprule, /**< propagation rule that deduced the value */
416  int pos /**< variable position, the propagation rule was applied at */
417  )
418 {
419  INFERINFO inferinfo;
420 
421  assert(pos >= 0);
422  /* in the inferinfo struct only 24 bits for 'pos' are reserved */
423  assert(pos < (1<<24));
425  inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
426  inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
427 
428  return inferinfo;
429 }
430 
431 /** constructs an inference information out of a propagation rule and a position number, returns info as int */
432 static
434  PROPRULE proprule, /**< propagation rule that deduced the value */
435  int pos /**< variable position, the propagation rule was applied at */
436  )
437 {
438  return inferInfoToInt(getInferInfo(proprule, pos));
439 }
440 
441 
442 /*
443  * memory growing methods for dynamically allocated arrays
444  */
445 
446 /** ensures, that linconsupgrades array can store at least num entries */
447 static
449  SCIP* scip, /**< SCIP data structure */
450  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
451  int num /**< minimum number of entries to store */
452  )
453 {
454  assert(scip != NULL);
455  assert(conshdlrdata != NULL);
456  assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
457 
458  if( num > conshdlrdata->linconsupgradessize )
459  {
460  int newsize;
461 
462  newsize = SCIPcalcMemGrowSize(scip, num);
463  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
464  conshdlrdata->linconsupgradessize = newsize;
465  }
466  assert(num <= conshdlrdata->linconsupgradessize);
468  return SCIP_OKAY;
469 }
470 
471 /** ensures, that vars and vals arrays can store at least num entries */
472 static
474  SCIP* scip, /**< SCIP data structure */
475  SCIP_CONSDATA* consdata, /**< linear constraint data */
476  int num /**< minimum number of entries to store */
477  )
478 {
479  assert(scip != NULL);
480  assert(consdata != NULL);
481  assert(consdata->nvars <= consdata->varssize);
482 
483  if( num > consdata->varssize )
484  {
485  int newsize;
486 
487  newsize = SCIPcalcMemGrowSize(scip, num);
488  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
489  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
490  if( consdata->eventdata != NULL )
491  {
492  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
493  }
494  consdata->varssize = newsize;
495  }
496  assert(num <= consdata->varssize);
497 
498  return SCIP_OKAY;
499 }
500 
501 
502 /*
503  * local methods for managing linear constraint update methods
504  */
505 
506 /** creates a linear constraint upgrade data object */
507 static
509  SCIP* scip, /**< SCIP data structure */
510  SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
511  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
512  int priority /**< priority of upgrading method */
513  )
514 {
515  assert(scip != NULL);
516  assert(linconsupgrade != NULL);
517  assert(linconsupgd != NULL);
518 
519  SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
520  (*linconsupgrade)->linconsupgd = linconsupgd;
521  (*linconsupgrade)->priority = priority;
522  (*linconsupgrade)->active = TRUE;
523 
524  return SCIP_OKAY;
525 }
526 
527 /** frees a linear constraint upgrade data object */
528 static
529 void linconsupgradeFree(
530  SCIP* scip, /**< SCIP data structure */
531  SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
532  )
533 {
534  assert(scip != NULL);
535  assert(linconsupgrade != NULL);
536  assert(*linconsupgrade != NULL);
537 
538  SCIPfreeBlockMemory(scip, linconsupgrade);
539 }
540 
541 /** creates constraint handler data for linear constraint handler */
542 static
544  SCIP* scip, /**< SCIP data structure */
545  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
546  SCIP_EVENTHDLR* eventhdlr /**< event handler */
547  )
548 {
549  assert(scip != NULL);
550  assert(conshdlrdata != NULL);
551  assert(eventhdlr != NULL);
552 
553  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
554  (*conshdlrdata)->linconsupgrades = NULL;
555  (*conshdlrdata)->linconsupgradessize = 0;
556  (*conshdlrdata)->nlinconsupgrades = 0;
557  (*conshdlrdata)->naddconss = 0;
558 
559  /* set event handler for updating linear constraint activity bounds */
560  (*conshdlrdata)->eventhdlr = eventhdlr;
561 
562  return SCIP_OKAY;
563 }
564 
565 /** frees constraint handler data for linear constraint handler */
566 static
567 void conshdlrdataFree(
568  SCIP* scip, /**< SCIP data structure */
569  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
570  )
571 {
572  int i;
573 
574  assert(scip != NULL);
575  assert(conshdlrdata != NULL);
576  assert(*conshdlrdata != NULL);
577 
578  for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
579  {
580  linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
581  }
582  SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
583 
584  SCIPfreeBlockMemory(scip, conshdlrdata);
585 }
587 /** creates a linear constraint upgrade data object */
588 static
590  SCIP* scip, /**< SCIP data structure */
591  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
592  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
593  const char* conshdlrname /**< name of the constraint handler */
594  )
595 {
596  int i;
597 
598  assert(scip != NULL);
599  assert(conshdlrdata != NULL);
600  assert(linconsupgd != NULL);
601  assert(conshdlrname != NULL);
602 
603  for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
604  {
605  if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
606  {
607 #ifdef SCIP_DEBUG
608  SCIPwarningMessage(scip, "Try to add already known upgrade message for constraint handler %s.\n", conshdlrname);
609 #endif
610  return TRUE;
611  }
612  }
613 
614  return FALSE;
615 }
616 
617 /** adds a linear constraint update method to the constraint handler's data */
618 static
620  SCIP* scip, /**< SCIP data structure */
621  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
622  SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
623  )
624 {
625  int i;
626 
627  assert(scip != NULL);
628  assert(conshdlrdata != NULL);
629  assert(linconsupgrade != NULL);
630 
631  SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
632 
633  for( i = conshdlrdata->nlinconsupgrades;
634  i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
635  {
636  conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
637  }
638  assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
639  conshdlrdata->linconsupgrades[i] = linconsupgrade;
640  conshdlrdata->nlinconsupgrades++;
641 
642  return SCIP_OKAY;
643 }
644 
645 /*
646  * local methods
647  */
648 
649 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
650 static
652  SCIP* scip, /**< SCIP data structure */
653  SCIP_CONS* cons, /**< linear constraint */
654  SCIP_VAR* var, /**< variable of constraint entry */
655  SCIP_Real val /**< coefficient of constraint entry */
656  )
657 {
658  SCIP_CONSDATA* consdata;
659 
660  assert(scip != NULL);
661  assert(cons != NULL);
662  assert(var != NULL);
663 
664  consdata = SCIPconsGetData(cons);
665  assert(consdata != NULL);
666  assert(!SCIPisZero(scip, val));
667 
668  if( SCIPisPositive(scip, val) )
669  {
670  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
671  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
672  }
673  else
674  {
675  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
676  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
677  }
678 
679  return SCIP_OKAY;
680 }
681 
682 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
683 static
685  SCIP* scip, /**< SCIP data structure */
686  SCIP_CONS* cons, /**< linear constraint */
687  SCIP_VAR* var, /**< variable of constraint entry */
688  SCIP_Real val /**< coefficient of constraint entry */
689  )
690 {
691  SCIP_CONSDATA* consdata;
692 
693  assert(scip != NULL);
694  assert(cons != NULL);
695  assert(var != NULL);
696 
697  consdata = SCIPconsGetData(cons);
698  assert(consdata != NULL);
699  assert(!SCIPisZero(scip, val));
700 
701  if( SCIPisPositive(scip, val) )
702  {
703  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, -consdata->lhs),
704  !SCIPisInfinity(scip, consdata->rhs)) );
705  }
706  else
707  {
708  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, consdata->rhs),
709  !SCIPisInfinity(scip, -consdata->lhs)) );
710  }
711 
712  return SCIP_OKAY;
713 }
714 
715 /** creates event data for variable at given position, and catches events */
716 /**! [SnippetDebugAssertions] */
717 static
719  SCIP* scip, /**< SCIP data structure */
720  SCIP_CONS* cons, /**< linear constraint */
721  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
722  int pos /**< array position of variable to catch bound change events for */
723  )
724 {
725  SCIP_CONSDATA* consdata;
726  assert(scip != NULL);
727  assert(cons != NULL);
728  assert(eventhdlr != NULL);
729 
730  consdata = SCIPconsGetData(cons);
731  assert(consdata != NULL);
732 
733  assert(0 <= pos && pos < consdata->nvars);
734  assert(consdata->vars != NULL);
735  assert(consdata->vars[pos] != NULL);
736  assert(SCIPvarIsTransformed(consdata->vars[pos]));
737  assert(consdata->eventdata != NULL);
738  assert(consdata->eventdata[pos] == NULL);
739 
740  SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
741  consdata->eventdata[pos]->cons = cons;
742  consdata->eventdata[pos]->varpos = pos;
743 
744  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
747  eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
748 
749  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(consdata->vars[pos]);
750 
751  return SCIP_OKAY;
752 }
753 /**! [SnippetDebugAssertions] */
754 
755 /** deletes event data for variable at given position, and drops events */
756 static
758  SCIP* scip, /**< SCIP data structure */
759  SCIP_CONS* cons, /**< linear constraint */
760  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
761  int pos /**< array position of variable to catch bound change events for */
762  )
763 {
764  SCIP_CONSDATA* consdata;
765  assert(scip != NULL);
766  assert(cons != NULL);
767  assert(eventhdlr != NULL);
768 
769  consdata = SCIPconsGetData(cons);
770  assert(consdata != NULL);
771 
772  assert(0 <= pos && pos < consdata->nvars);
773  assert(consdata->vars[pos] != NULL);
774  assert(consdata->eventdata != NULL);
775  assert(consdata->eventdata[pos] != NULL);
776  assert(consdata->eventdata[pos]->cons == cons);
777  assert(consdata->eventdata[pos]->varpos == pos);
778 
779  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
782  eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
783 
784  SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
785 
786  return SCIP_OKAY;
787 }
788 
789 /** catches bound change events for all variables in transformed linear constraint */
790 static
792  SCIP* scip, /**< SCIP data structure */
793  SCIP_CONS* cons, /**< linear constraint */
794  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
795  )
796 {
797  SCIP_CONSDATA* consdata;
798  int i;
799 
800  assert(scip != NULL);
801  assert(cons != NULL);
802 
803  consdata = SCIPconsGetData(cons);
804  assert(consdata != NULL);
805  assert(consdata->eventdata == NULL);
806 
807  /* allocate eventdata array */
808  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
809  assert(consdata->eventdata != NULL);
810  BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
811 
812  /* catch event for every single variable */
813  for( i = 0; i < consdata->nvars; ++i )
814  {
815  SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
816  }
817 
818  return SCIP_OKAY;
819 }
820 
821 /** drops bound change events for all variables in transformed linear constraint */
822 static
824  SCIP* scip, /**< SCIP data structure */
825  SCIP_CONS* cons, /**< linear constraint */
826  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
827  )
828 {
829  SCIP_CONSDATA* consdata;
830  int i;
831 
832  assert(scip != NULL);
833  assert(cons != NULL);
834 
835  consdata = SCIPconsGetData(cons);
836  assert(consdata != NULL);
837  assert(consdata->eventdata != NULL);
838 
839  /* drop event of every single variable */
840  for( i = consdata->nvars - 1; i >= 0; --i )
841  {
842  SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
843  }
844 
845  /* free eventdata array */
846  SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
847  assert(consdata->eventdata == NULL);
848 
849  return SCIP_OKAY;
850 }
851 
852 /** creates a linear constraint data */
853 static
855  SCIP* scip, /**< SCIP data structure */
856  SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
857  int nvars, /**< number of nonzeros in the constraint */
858  SCIP_VAR** vars, /**< array with variables of constraint entries */
859  SCIP_Real* vals, /**< array with coefficients of constraint entries */
860  SCIP_Real lhs, /**< left hand side of row */
861  SCIP_Real rhs /**< right hand side of row */
862  )
863 {
864  int v;
865  SCIP_Real constant;
866 
867  assert(scip != NULL);
868  assert(consdata != NULL);
869  assert(nvars == 0 || vars != NULL);
870  assert(nvars == 0 || vals != NULL);
871 
872  if( SCIPisInfinity(scip, rhs) )
873  rhs = SCIPinfinity(scip);
874  else if( SCIPisInfinity(scip, -rhs) )
875  rhs = -SCIPinfinity(scip);
876 
877  if( SCIPisInfinity(scip, -lhs) )
878  lhs = -SCIPinfinity(scip);
879  else if( SCIPisInfinity(scip, lhs) )
880  lhs = SCIPinfinity(scip);
881 
882  if( SCIPisGT(scip, lhs, rhs) )
883  {
884  SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
885  SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
886  }
887 
888  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
889 
890  (*consdata)->varssize = 0;
891  (*consdata)->nvars = nvars;
892  (*consdata)->hascontvar = FALSE;
893  (*consdata)->hasnonbinvar = FALSE;
894  (*consdata)->hasnonbinvalid = TRUE;
895  (*consdata)->vars = NULL;
896  (*consdata)->vals = NULL;
897 
898  constant = 0.0;
899  if( nvars > 0 )
900  {
901  int k;
902 
903  SCIP_VAR** varsbuffer;
904  SCIP_Real* valsbuffer;
905 
906  /* copy variables into temporary buffer */
907  SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
908  SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
909  k = 0;
910 
911  /* loop over variables and sort out fixed ones */
912  for( v = 0; v < nvars; ++v )
913  {
914  SCIP_VAR* var;
915  SCIP_Real val;
916 
917  var = vars[v];
918  val = vals[v];
919 
920  assert(var != NULL);
921  if( !SCIPisZero(scip, val) )
922  {
923  /* treat fixed variable as a constant if problem compression is enabled */
925  {
926  constant += SCIPvarGetLbGlobal(var) * val;
927  }
928  else
929  {
930  varsbuffer[k] = var;
931  valsbuffer[k] = val;
932  k++;
933 
934  /* update hascontvar and hasnonbinvar flags */
935  if( !(*consdata)->hascontvar )
936  {
937  SCIP_VARTYPE vartype = SCIPvarGetType(var);
938 
939  if( vartype != SCIP_VARTYPE_BINARY )
940  {
941  (*consdata)->hasnonbinvar = TRUE;
942 
943  if( vartype == SCIP_VARTYPE_CONTINUOUS )
944  (*consdata)->hascontvar = TRUE;
945  }
946  }
947  }
948  }
949  }
950  (*consdata)->nvars = k;
951 
952  if( k > 0 )
953  {
954  /* copy the possibly reduced buffer arrays into block */
955  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
956  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) );
957  (*consdata)->varssize = k;
958  }
959  /* free temporary buffer */
960  SCIPfreeBufferArray(scip, &valsbuffer);
961  SCIPfreeBufferArray(scip, &varsbuffer);
962  }
963 
964  (*consdata)->eventdata = NULL;
965 
966  /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
967  if( !SCIPisZero(scip, constant) )
968  {
969  if( !SCIPisInfinity(scip, REALABS(lhs)) )
970  lhs -= constant;
971 
972  if( !SCIPisInfinity(scip, REALABS(rhs)) )
973  rhs -= constant;
974  }
975 
976  (*consdata)->row = NULL;
977  (*consdata)->nlrow = NULL;
978  (*consdata)->lhs = lhs;
979  (*consdata)->rhs = rhs;
980  (*consdata)->maxabsval = SCIP_INVALID;
981  (*consdata)->minabsval = SCIP_INVALID;
982  QUAD_ASSIGN((*consdata)->minactivity, SCIP_INVALID);
983  QUAD_ASSIGN((*consdata)->maxactivity, SCIP_INVALID);
984  (*consdata)->lastminactivity = SCIP_INVALID;
985  (*consdata)->lastmaxactivity = SCIP_INVALID;
986  (*consdata)->maxactdelta = SCIP_INVALID;
987  (*consdata)->maxactdeltavar = NULL;
988  (*consdata)->minactivityneginf = -1;
989  (*consdata)->minactivityposinf = -1;
990  (*consdata)->maxactivityneginf = -1;
991  (*consdata)->maxactivityposinf = -1;
992  (*consdata)->minactivityneghuge = -1;
993  (*consdata)->minactivityposhuge = -1;
994  (*consdata)->maxactivityneghuge = -1;
995  (*consdata)->maxactivityposhuge = -1;
996  QUAD_ASSIGN((*consdata)->glbminactivity, SCIP_INVALID);
997  QUAD_ASSIGN((*consdata)->glbmaxactivity, SCIP_INVALID);
998  (*consdata)->lastglbminactivity = SCIP_INVALID;
999  (*consdata)->lastglbmaxactivity = SCIP_INVALID;
1000  (*consdata)->glbminactivityneginf = -1;
1001  (*consdata)->glbminactivityposinf = -1;
1002  (*consdata)->glbmaxactivityneginf = -1;
1003  (*consdata)->glbmaxactivityposinf = -1;
1004  (*consdata)->glbminactivityneghuge = -1;
1005  (*consdata)->glbminactivityposhuge = -1;
1006  (*consdata)->glbmaxactivityneghuge = -1;
1007  (*consdata)->glbmaxactivityposhuge = -1;
1008  (*consdata)->possignature = 0;
1009  (*consdata)->negsignature = 0;
1010  (*consdata)->validmaxabsval = FALSE;
1011  (*consdata)->validminabsval = FALSE;
1012  (*consdata)->validactivities = FALSE;
1013  (*consdata)->validminact = FALSE;
1014  (*consdata)->validmaxact = FALSE;
1015  (*consdata)->validglbminact = FALSE;
1016  (*consdata)->validglbmaxact = FALSE;
1017  (*consdata)->boundstightened = 0;
1018  (*consdata)->presolved = FALSE;
1019  (*consdata)->removedfixings = FALSE;
1020  (*consdata)->validsignature = FALSE;
1021  (*consdata)->changed = TRUE;
1022  (*consdata)->normalized = FALSE;
1023  (*consdata)->upgradetried = FALSE;
1024  (*consdata)->upgraded = FALSE;
1025  (*consdata)->indexsorted = (nvars <= 1);
1026  (*consdata)->merged = (nvars <= 1);
1027  (*consdata)->cliquesadded = FALSE;
1028  (*consdata)->implsadded = FALSE;
1029  (*consdata)->coefsorted = FALSE;
1030  (*consdata)->nbinvars = -1;
1031  (*consdata)->varsdeleted = FALSE;
1032  (*consdata)->rangedrowpropagated = 0;
1033  (*consdata)->checkabsolute = FALSE;
1034 
1035  if( SCIPisTransformed(scip) )
1036  {
1037  /* get transformed variables */
1038  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1039  }
1040 
1041  /* capture variables */
1042  for( v = 0; v < (*consdata)->nvars; v++ )
1043  {
1044  /* likely implies a deleted variable */
1045  if( (*consdata)->vars[v] == NULL )
1046  {
1047  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1048  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1049  SCIPfreeBlockMemory(scip, consdata);
1050  return SCIP_INVALIDDATA;
1051  }
1052 
1053  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1054  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1055  }
1056 
1057  return SCIP_OKAY;
1058 }
1059 
1060 /** frees a linear constraint data */
1061 static
1063  SCIP* scip, /**< SCIP data structure */
1064  SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1065  )
1066 {
1067  int v;
1068 
1069  assert(scip != NULL);
1070  assert(consdata != NULL);
1071  assert(*consdata != NULL);
1072  assert((*consdata)->varssize >= 0);
1073 
1074  /* release the row */
1075  if( (*consdata)->row != NULL )
1076  {
1077  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1078  }
1079 
1080  /* release the nlrow */
1081  if( (*consdata)->nlrow != NULL )
1082  {
1083  SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
1084  }
1085 
1086  /* release variables */
1087  for( v = 0; v < (*consdata)->nvars; v++ )
1088  {
1089  assert((*consdata)->vars[v] != NULL);
1090  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1091  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1092  }
1093 
1094  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1095  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1096  SCIPfreeBlockMemory(scip, consdata);
1097 
1098  return SCIP_OKAY;
1099 }
1100 
1101 /** prints linear constraint in CIP format to file stream */
1102 static
1104  SCIP* scip, /**< SCIP data structure */
1105  SCIP_CONSDATA* consdata, /**< linear constraint data */
1106  FILE* file /**< output file (or NULL for standard output) */
1107  )
1108 {
1109  assert(scip != NULL);
1110  assert(consdata != NULL);
1111 
1112  /* print left hand side for ranged rows */
1113  if( !SCIPisInfinity(scip, -consdata->lhs)
1114  && !SCIPisInfinity(scip, consdata->rhs)
1115  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1116  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1117 
1118  /* print coefficients and variables */
1119  if( consdata->nvars == 0 )
1120  SCIPinfoMessage(scip, file, "0");
1121  else
1122  {
1123  /* post linear sum of the linear constraint */
1124  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1125  }
1126 
1127  /* print right hand side */
1128  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1129  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1130  else if( !SCIPisInfinity(scip, consdata->rhs) )
1131  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1132  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1133  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1134  else
1135  SCIPinfoMessage(scip, file, " [free]");
1136 
1137  return SCIP_OKAY;
1138 }
1139 
1140 /** prints linear constraint and contained solution values of variables to file stream */
1141 static
1143  SCIP* scip, /**< SCIP data structure */
1144  SCIP_CONS* cons, /**< linear constraint */
1145  SCIP_SOL* sol, /**< solution to print */
1146  FILE* file /**< output file (or NULL for standard output) */
1147  )
1148 {
1149  SCIP_CONSDATA* consdata;
1150 
1151  assert(scip != NULL);
1152  assert(cons != NULL);
1153 
1154  consdata = SCIPconsGetData(cons);
1155  assert(consdata != NULL);
1156 
1158 
1159  /* print left hand side for ranged rows */
1160  if( !SCIPisInfinity(scip, -consdata->lhs)
1161  && !SCIPisInfinity(scip, consdata->rhs)
1162  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1163  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1164 
1165  /* print coefficients and variables */
1166  if( consdata->nvars == 0 )
1167  SCIPinfoMessage(scip, file, "0");
1168  else
1169  {
1170  int v;
1171 
1172  /* post linear sum of the linear constraint */
1173  for( v = 0; v < consdata->nvars; ++v )
1174  {
1175  if( consdata->vals != NULL )
1176  {
1177  if( consdata->vals[v] == 1.0 )
1178  {
1179  if( v > 0 )
1180  SCIPinfoMessage(scip, file, " +");
1181  }
1182  else if( consdata->vals[v] == -1.0 )
1183  SCIPinfoMessage(scip, file, " -");
1184  else
1185  SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1186  }
1187  else if( consdata->nvars > 0 )
1188  SCIPinfoMessage(scip, file, " +");
1189 
1190  /* print variable name */
1191  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1192 
1193  SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1194  }
1195  }
1196 
1197  /* print right hand side */
1198  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1199  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1200  else if( !SCIPisInfinity(scip, consdata->rhs) )
1201  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1202  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1203  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1204  else
1205  SCIPinfoMessage(scip, file, " [free]");
1206 
1207  SCIPinfoMessage(scip, file, ";\n");
1208 
1209  return SCIP_OKAY;
1210 }
1211 
1212 /** invalidates activity bounds, such that they are recalculated in next get */
1213 static
1215  SCIP_CONSDATA* consdata /**< linear constraint */
1216  )
1217 {
1218  assert(consdata != NULL);
1219 
1220  consdata->validactivities = FALSE;
1221  consdata->validminact = FALSE;
1222  consdata->validmaxact = FALSE;
1223  consdata->validglbminact = FALSE;
1224  consdata->validglbmaxact = FALSE;
1225  consdata->validmaxabsval = FALSE;
1226  consdata->validminabsval = FALSE;
1227  consdata->hasnonbinvalid = FALSE;
1228  QUAD_ASSIGN(consdata->minactivity, SCIP_INVALID);
1229  QUAD_ASSIGN(consdata->maxactivity, SCIP_INVALID);
1230  consdata->lastminactivity = SCIP_INVALID;
1231  consdata->lastmaxactivity = SCIP_INVALID;
1232  consdata->maxabsval = SCIP_INVALID;
1233  consdata->minabsval = SCIP_INVALID;
1234  consdata->maxactdelta = SCIP_INVALID;
1235  consdata->maxactdeltavar = NULL;
1236  consdata->minactivityneginf = -1;
1237  consdata->minactivityposinf = -1;
1238  consdata->maxactivityneginf = -1;
1239  consdata->maxactivityposinf = -1;
1240  consdata->minactivityneghuge = -1;
1241  consdata->minactivityposhuge = -1;
1242  consdata->maxactivityneghuge = -1;
1243  consdata->maxactivityposhuge = -1;
1244  QUAD_ASSIGN(consdata->glbminactivity, SCIP_INVALID);
1245  QUAD_ASSIGN(consdata->glbmaxactivity, SCIP_INVALID);
1246  consdata->lastglbminactivity = SCIP_INVALID;
1247  consdata->lastglbmaxactivity = SCIP_INVALID;
1248  consdata->glbminactivityneginf = -1;
1249  consdata->glbminactivityposinf = -1;
1250  consdata->glbmaxactivityneginf = -1;
1251  consdata->glbmaxactivityposinf = -1;
1252  consdata->glbminactivityneghuge = -1;
1253  consdata->glbminactivityposhuge = -1;
1254  consdata->glbmaxactivityneghuge = -1;
1255  consdata->glbmaxactivityposhuge = -1;
1256 }
1257 
1258 /** compute the pseudo activity of a constraint */
1259 static
1261  SCIP* scip, /**< SCIP data structure */
1262  SCIP_CONSDATA* consdata /**< linear constraint data */
1263  )
1264 {
1265  int i;
1266  int pseudoactivityposinf;
1267  int pseudoactivityneginf;
1268  SCIP_Real pseudoactivity;
1269  SCIP_Real bound;
1270  SCIP_Real val;
1271 
1272  pseudoactivity = 0;
1273  pseudoactivityposinf = 0;
1274  pseudoactivityneginf = 0;
1275 
1276  for( i = consdata->nvars - 1; i >= 0; --i )
1277  {
1278  val = consdata->vals[i];
1279  bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1280  if( SCIPisInfinity(scip, bound) )
1281  {
1282  if( val > 0.0 )
1283  pseudoactivityposinf++;
1284  else
1285  pseudoactivityneginf++;
1286  }
1287  else
1288  {
1289  if( SCIPisInfinity(scip, -bound) )
1290  {
1291  if( val > 0.0 )
1292  pseudoactivityneginf++;
1293  else
1294  pseudoactivityposinf++;
1295  }
1296  else
1297  pseudoactivity += val * bound;
1298  }
1299  }
1300 
1301  if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1302  return SCIP_INVALID;
1303  else if( pseudoactivityneginf > 0 )
1304  return -SCIPinfinity(scip);
1305  else if( pseudoactivityposinf > 0 )
1306  return SCIPinfinity(scip);
1307 
1308  return pseudoactivity;
1309 }
1310 
1311 /** recompute the minactivity of a constraint */
1312 static
1314  SCIP* scip, /**< SCIP data structure */
1315  SCIP_CONSDATA* consdata /**< linear constraint data */
1316  )
1317 {
1318  int i;
1319  SCIP_Real bound;
1320 
1321  QUAD_ASSIGN(consdata->minactivity, 0.0);
1322 
1323  for( i = consdata->nvars - 1; i >= 0; --i )
1324  {
1325  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1326  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1327  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1328  SCIPquadprecSumQD(consdata->minactivity, consdata->minactivity, consdata->vals[i] * bound);
1329  }
1330 
1331  /* the activity was just computed from scratch and is valid now */
1332  consdata->validminact = TRUE;
1333 
1334  /* the activity was just computed from scratch, mark it to be reliable */
1335  consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
1336 }
1337 
1338 /** recompute the maxactivity of a constraint */
1339 static
1341  SCIP* scip, /**< SCIP data structure */
1342  SCIP_CONSDATA* consdata /**< linear constraint data */
1343  )
1344 {
1345  int i;
1346  SCIP_Real bound;
1347 
1348  QUAD_ASSIGN(consdata->maxactivity, 0.0);
1349 
1350  for( i = consdata->nvars - 1; i >= 0; --i )
1351  {
1352  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1353  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1354  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1355  SCIPquadprecSumQD(consdata->maxactivity, consdata->maxactivity, consdata->vals[i] * bound);
1356  }
1357 
1358  /* the activity was just computed from scratch and is valid now */
1359  consdata->validmaxact = TRUE;
1360 
1361  /* the activity was just computed from scratch, mark it to be reliable */
1362  consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
1363 }
1364 
1365 /** recompute the global minactivity of a constraint */
1366 static
1368  SCIP* scip, /**< SCIP data structure */
1369  SCIP_CONSDATA* consdata /**< linear constraint data */
1370  )
1371 {
1372  int i;
1373  SCIP_Real bound;
1374 
1375  QUAD_ASSIGN(consdata->glbminactivity, 0.0);
1376 
1377  for( i = consdata->nvars - 1; i >= 0; --i )
1378  {
1379  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1380  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1381  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1382  SCIPquadprecSumQD(consdata->glbminactivity, consdata->glbminactivity, consdata->vals[i] * bound);
1383  }
1384 
1385  /* the activity was just computed from scratch and is valid now */
1386  consdata->validglbminact = TRUE;
1387 
1388  /* the activity was just computed from scratch, mark it to be reliable */
1389  consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
1390 }
1391 
1392 /** recompute the global maxactivity of a constraint */
1393 static
1395  SCIP* scip, /**< SCIP data structure */
1396  SCIP_CONSDATA* consdata /**< linear constraint data */
1397  )
1398 {
1399  int i;
1400  SCIP_Real bound;
1401 
1402  QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
1403 
1404  for( i = consdata->nvars - 1; i >= 0; --i )
1405  {
1406  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1407  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1408  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1409  SCIPquadprecSumQD(consdata->glbmaxactivity, consdata->glbmaxactivity, consdata->vals[i] * bound);
1410  }
1411 
1412  /* the activity was just computed from scratch and is valid now */
1413  consdata->validglbmaxact = TRUE;
1414 
1415  /* the activity was just computed from scratch, mark it to be reliable */
1416  consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
1417 }
1418 
1419 /** calculates maximum absolute value of coefficients */
1420 static
1422  SCIP_CONSDATA* consdata /**< linear constraint data */
1423  )
1424 {
1425  SCIP_Real absval;
1426  int i;
1427 
1428  assert(consdata != NULL);
1429  assert(!consdata->validmaxabsval);
1430  assert(consdata->maxabsval >= SCIP_INVALID);
1431 
1432  consdata->validmaxabsval = TRUE;
1433  consdata->maxabsval = 0.0;
1434  for( i = 0; i < consdata->nvars; ++i )
1435  {
1436  absval = consdata->vals[i];
1437  absval = REALABS(absval);
1438  if( absval > consdata->maxabsval )
1439  consdata->maxabsval = absval;
1440  }
1441 }
1442 
1443 /** calculates minimum absolute value of coefficients */
1444 static
1446  SCIP_CONSDATA* consdata /**< linear constraint data */
1447  )
1448 {
1449  SCIP_Real absval;
1450  int i;
1451 
1452  assert(consdata != NULL);
1453  assert(!consdata->validminabsval);
1454  assert(consdata->minabsval >= SCIP_INVALID);
1455 
1456  consdata->validminabsval = TRUE;
1457 
1458  if( consdata->nvars > 0 )
1459  consdata->minabsval = REALABS(consdata->vals[0]);
1460  else
1461  consdata->minabsval = 0.0;
1462 
1463  for( i = 1; i < consdata->nvars; ++i )
1464  {
1465  absval = consdata->vals[i];
1466  absval = REALABS(absval);
1467  if( absval < consdata->minabsval )
1468  consdata->minabsval = absval;
1469  }
1470 }
1471 
1472 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1473 static
1475  SCIP_CONSDATA* consdata /**< linear constraint data */
1476  )
1477 {
1478  int v;
1479 
1480  assert(!consdata->hasnonbinvalid);
1481  consdata->hasnonbinvar = FALSE;
1482  consdata->hascontvar = FALSE;
1483 
1484  for( v = consdata->nvars - 1; v >= 0; --v )
1485  {
1486  SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1487 
1488  if( vartype != SCIP_VARTYPE_BINARY )
1489  {
1490  consdata->hasnonbinvar = TRUE;
1491 
1492  if( vartype == SCIP_VARTYPE_CONTINUOUS )
1493  {
1494  consdata->hascontvar = TRUE;
1495  break;
1496  }
1497  }
1498  }
1499  assert(consdata->hascontvar || v < 0);
1500 
1501  consdata->hasnonbinvalid = TRUE;
1502 }
1503 
1504 
1505 #ifdef CHECKMAXACTDELTA
1506 /** checks that the stored maximal activity delta (if not invalid) is correct */
1507 static
1509  SCIP* scip, /**< SCIP data structure */
1510  SCIP_CONSDATA* consdata /**< linear constraint data */
1511  )
1512 {
1513  if( consdata->maxactdelta != SCIP_INVALID )
1514  {
1515  SCIP_Real maxactdelta = 0.0;
1516  SCIP_Real domain;
1517  SCIP_Real delta;
1518  SCIP_Real lb;
1519  SCIP_Real ub;
1520  int v;
1521 
1522  for( v = consdata->nvars - 1; v >= 0; --v )
1523  {
1524  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1525  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1526 
1527  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1528  {
1529  maxactdelta = SCIPinfinity(scip);
1530  break;
1531  }
1532 
1533  domain = ub - lb;
1534  delta = REALABS(consdata->vals[v]) * domain;
1535 
1536  if( delta > maxactdelta )
1537  {
1538  maxactdelta = delta;
1539  }
1540  }
1541  assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1542  }
1543 }
1544 #else
1545 #define checkMaxActivityDelta(scip, consdata) /**/
1546 #endif
1547 
1548 /** recompute maximal activity contribution for a single variable */
1549 static
1551  SCIP* scip, /**< SCIP data structure */
1552  SCIP_CONSDATA* consdata /**< linear constraint data */
1553  )
1554 {
1555  SCIP_Real delta;
1556  int v;
1557 
1558  consdata->maxactdelta = 0.0;
1559 
1560  if( !consdata->hasnonbinvalid )
1561  consdataCheckNonbinvar(consdata);
1562 
1563  /* easy case, the problem consists only of binary variables */
1564  if( !consdata->hasnonbinvar )
1565  {
1566  for( v = consdata->nvars - 1; v >= 0; --v )
1567  {
1568  if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1569  {
1570  delta = REALABS(consdata->vals[v]);
1571 
1572  if( delta > consdata->maxactdelta )
1573  {
1574  consdata->maxactdelta = delta;
1575  consdata->maxactdeltavar = consdata->vars[v];
1576  }
1577  }
1578  }
1579  return;
1580  }
1581 
1582  for( v = consdata->nvars - 1; v >= 0; --v )
1583  {
1584  SCIP_Real domain;
1585  SCIP_Real lb;
1586  SCIP_Real ub;
1587 
1588  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1589  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1590 
1591  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1592  {
1593  consdata->maxactdelta = SCIPinfinity(scip);
1594  consdata->maxactdeltavar = consdata->vars[v];
1595  break;
1596  }
1597 
1598  domain = ub - lb;
1599  delta = REALABS(consdata->vals[v]) * domain;
1600 
1601  if( delta > consdata->maxactdelta )
1602  {
1603  consdata->maxactdelta = delta;
1604  consdata->maxactdeltavar = consdata->vars[v];
1605  }
1606  }
1607 }
1608 
1609 
1610 /** updates activities for a change in a bound */
1611 static
1613  SCIP* scip, /**< SCIP data structure */
1614  SCIP_CONSDATA* consdata, /**< linear constraint data */
1615  SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1616  SCIP_Real oldbound, /**< old bound of variable */
1617  SCIP_Real newbound, /**< new bound of variable */
1618  SCIP_Real val, /**< coefficient of constraint entry */
1619  SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1620  SCIP_Bool global, /**< is it a global or a local bound change? */
1621  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1622  )
1623 {
1624  QUAD_MEMBER(SCIP_Real* activity);
1625  QUAD_MEMBER(SCIP_Real delta);
1626  SCIP_Real* lastactivity;
1627  int* activityposinf;
1628  int* activityneginf;
1629  int* activityposhuge;
1630  int* activityneghuge;
1631  SCIP_Real oldcontribution;
1632  SCIP_Real newcontribution;
1633  SCIP_Bool validact;
1634  SCIP_Bool finitenewbound;
1635  SCIP_Bool hugevalnewcont;
1636 
1637  assert(scip != NULL);
1638  assert(consdata != NULL);
1639  assert(global || (var != NULL));
1640  assert(consdata->validactivities);
1641  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
1642  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
1643  assert(consdata->lastminactivity < SCIP_INVALID);
1644  assert(consdata->lastmaxactivity < SCIP_INVALID);
1645  assert(consdata->minactivityneginf >= 0);
1646  assert(consdata->minactivityposinf >= 0);
1647  assert(consdata->maxactivityneginf >= 0);
1648  assert(consdata->maxactivityposinf >= 0);
1649  assert(consdata->minactivityneghuge >= 0);
1650  assert(consdata->minactivityposhuge >= 0);
1651  assert(consdata->maxactivityneghuge >= 0);
1652  assert(consdata->maxactivityposhuge >= 0);
1653  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
1654  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
1655  assert(consdata->lastglbminactivity < SCIP_INVALID);
1656  assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1657  assert(consdata->glbminactivityneginf >= 0);
1658  assert(consdata->glbminactivityposinf >= 0);
1659  assert(consdata->glbmaxactivityneginf >= 0);
1660  assert(consdata->glbmaxactivityposinf >= 0);
1661  assert(consdata->glbminactivityneghuge >= 0);
1662  assert(consdata->glbminactivityposhuge >= 0);
1663  assert(consdata->glbmaxactivityneghuge >= 0);
1664  assert(consdata->glbmaxactivityposhuge >= 0);
1665 
1666  QUAD_ASSIGN(delta, 0.0);
1667 
1668  /* we are updating global activities */
1669  if( global )
1670  {
1671  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1672  * lower bound + pos. coef: update minactivity
1673  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1674  * upper bound + pos. coef: update maxactivity
1675  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1676  */
1677  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1678  {
1679  if( val > 0.0 )
1680  {
1681  QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1682  lastactivity = &(consdata->lastglbminactivity);
1683  activityposinf = &(consdata->glbminactivityposinf);
1684  activityneginf = &(consdata->glbminactivityneginf);
1685  activityposhuge = &(consdata->glbminactivityposhuge);
1686  activityneghuge = &(consdata->glbminactivityneghuge);
1687  validact = consdata->validglbminact;
1688  }
1689  else
1690  {
1691  QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1692  lastactivity = &(consdata->lastglbmaxactivity);
1693  activityposinf = &(consdata->glbmaxactivityneginf);
1694  activityneginf = &(consdata->glbmaxactivityposinf);
1695  activityposhuge = &(consdata->glbmaxactivityposhuge);
1696  activityneghuge = &(consdata->glbmaxactivityneghuge);
1697  validact = consdata->validglbmaxact;
1698  }
1699  }
1700  else
1701  {
1702  if( val > 0.0 )
1703  {
1704  QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1705  lastactivity = &(consdata->lastglbmaxactivity);
1706  activityposinf = &(consdata->glbmaxactivityposinf);
1707  activityneginf = &(consdata->glbmaxactivityneginf);
1708  activityposhuge = &(consdata->glbmaxactivityposhuge);
1709  activityneghuge = &(consdata->glbmaxactivityneghuge);
1710  validact = consdata->validglbmaxact;
1711  }
1712  else
1713  {
1714  QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1715  lastactivity = &(consdata->lastglbminactivity);
1716  activityposinf = &(consdata->glbminactivityneginf);
1717  activityneginf = &(consdata->glbminactivityposinf);
1718  activityposhuge = &(consdata->glbminactivityposhuge);
1719  activityneghuge = &(consdata->glbminactivityneghuge);
1720  validact = consdata->validglbminact;
1721  }
1722  }
1723  }
1724  /* we are updating local activities */
1725  else
1726  {
1727  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1728  * lower bound + pos. coef: update minactivity
1729  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1730  * upper bound + pos. coef: update maxactivity
1731  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1732  */
1733  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1734  {
1735  if( val > 0.0 )
1736  {
1737  QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1738  lastactivity = &(consdata->lastminactivity);
1739  activityposinf = &(consdata->minactivityposinf);
1740  activityneginf = &(consdata->minactivityneginf);
1741  activityposhuge = &(consdata->minactivityposhuge);
1742  activityneghuge = &(consdata->minactivityneghuge);
1743  validact = consdata->validminact;
1744  }
1745  else
1746  {
1747  QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1748  lastactivity = &(consdata->lastmaxactivity);
1749  activityposinf = &(consdata->maxactivityneginf);
1750  activityneginf = &(consdata->maxactivityposinf);
1751  activityposhuge = &(consdata->maxactivityposhuge);
1752  activityneghuge = &(consdata->maxactivityneghuge);
1753  validact = consdata->validmaxact;
1754  }
1755  }
1756  else
1757  {
1758  if( val > 0.0 )
1759  {
1760  QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1761  lastactivity = &(consdata->lastmaxactivity);
1762  activityposinf = &(consdata->maxactivityposinf);
1763  activityneginf = &(consdata->maxactivityneginf);
1764  activityposhuge = &(consdata->maxactivityposhuge);
1765  activityneghuge = &(consdata->maxactivityneghuge);
1766  validact = consdata->validmaxact;
1767  }
1768  else
1769  {
1770  QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1771  lastactivity = &(consdata->lastminactivity);
1772  activityposinf = &(consdata->minactivityneginf);
1773  activityneginf = &(consdata->minactivityposinf);
1774  activityposhuge = &(consdata->minactivityposhuge);
1775  activityneghuge = &(consdata->minactivityneghuge);
1776  validact = consdata->validminact;
1777  }
1778  }
1779  }
1780 
1781  oldcontribution = val * oldbound;
1782  newcontribution = val * newbound;
1783  hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1784  finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1785 
1786  if( SCIPisInfinity(scip, REALABS(oldbound)) )
1787  {
1788  /* old bound was +infinity */
1789  if( oldbound > 0.0 )
1790  {
1791  assert((*activityposinf) >= 1);
1792 
1793  /* we only have to do something if the new bound is not again +infinity */
1794  if( finitenewbound || newbound < 0.0 )
1795  {
1796  /* decrease the counter for positive infinite contributions */
1797  (*activityposinf)--;
1798 
1799  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1800  if( !finitenewbound && newbound < 0.0 )
1801  (*activityneginf)++;
1802  else if( hugevalnewcont )
1803  {
1804  /* if the contribution of this variable is too large, increase the counter for huge values */
1805  if( newcontribution > 0.0 )
1806  (*activityposhuge)++;
1807  else
1808  (*activityneghuge)++;
1809  }
1810  /* "normal case": just add the contribution to the activity */
1811  else
1812  QUAD_ASSIGN(delta, newcontribution);
1813  }
1814  }
1815  /* old bound was -infinity */
1816  else
1817  {
1818  assert(oldbound < 0.0);
1819  assert((*activityneginf) >= 1);
1820 
1821  /* we only have to do something ig the new bound is not again -infinity */
1822  if( finitenewbound || newbound > 0.0 )
1823  {
1824  /* decrease the counter for negative infinite contributions */
1825  (*activityneginf)--;
1826 
1827  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1828  if( !finitenewbound && newbound > 0.0 )
1829  (*activityposinf)++;
1830  else if( hugevalnewcont )
1831  {
1832  /* if the contribution of this variable is too large, increase the counter for huge values */
1833  if( newcontribution > 0.0 )
1834  (*activityposhuge)++;
1835  else
1836  (*activityneghuge)++;
1837  }
1838  /* "normal case": just add the contribution to the activity */
1839  else
1840  QUAD_ASSIGN(delta, newcontribution);
1841  }
1842  }
1843  }
1844  else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1845  {
1846  /* old contribution was too large and positive */
1847  if( oldcontribution > 0.0 )
1848  {
1849  assert((*activityposhuge) >= 1);
1850 
1851  /* decrease the counter for huge positive contributions; it might be increased again later,
1852  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1853  */
1854  (*activityposhuge)--;
1855 
1856  if( !finitenewbound )
1857  {
1858  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1859  if( newbound > 0.0 )
1860  (*activityposinf)++;
1861  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1862  else
1863  (*activityneginf)++;
1864  }
1865  else if( hugevalnewcont )
1866  {
1867  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1868  if( newcontribution > 0.0 )
1869  (*activityposhuge)++;
1870  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1871  else
1872  (*activityneghuge)++;
1873  }
1874  /* "normal case": just add the contribution to the activity */
1875  else
1876  QUAD_ASSIGN(delta, newcontribution);
1877  }
1878  /* old contribution was too large and negative */
1879  else
1880  {
1881  assert(oldcontribution < 0.0);
1882  assert((*activityneghuge) >= 1);
1883 
1884  /* decrease the counter for huge negative contributions; it might be increased again later,
1885  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1886  */
1887  (*activityneghuge)--;
1888 
1889  if( !finitenewbound )
1890  {
1891  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1892  if( newbound > 0.0 )
1893  (*activityposinf)++;
1894  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1895  else
1896  (*activityneginf)++;
1897  }
1898  else if( hugevalnewcont )
1899  {
1900  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1901  if( newcontribution > 0.0 )
1902  (*activityposhuge)++;
1903  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1904  else
1905  (*activityneghuge)++;
1906  }
1907  /* "normal case": just add the contribution to the activity */
1908  else
1909  QUAD_ASSIGN(delta, newcontribution);
1910  }
1911  }
1912  /* old bound was finite and not too large */
1913  else
1914  {
1915  if( !finitenewbound )
1916  {
1917  /* if the new bound is +infinity, the old contribution has to be subtracted
1918  * and the counter for positive infinite contributions has to be increased
1919  */
1920  if( newbound > 0.0 )
1921  {
1922  (*activityposinf)++;
1923  QUAD_ASSIGN(delta, -oldcontribution);
1924  }
1925  /* if the new bound is -infinity, the old contribution has to be subtracted
1926  * and the counter for negative infinite contributions has to be increased
1927  */
1928  else
1929  {
1930  assert(newbound < 0.0 );
1931 
1932  (*activityneginf)++;
1933  QUAD_ASSIGN(delta, -oldcontribution);
1934  }
1935  }
1936  /* if the contribution of this variable is too large, increase the counter for huge values */
1937  else if( hugevalnewcont )
1938  {
1939  if( newcontribution > 0.0 )
1940  {
1941  (*activityposhuge)++;
1942  QUAD_ASSIGN(delta, -oldcontribution);
1943  }
1944  else
1945  {
1946  (*activityneghuge)++;
1947  QUAD_ASSIGN(delta, -oldcontribution);
1948  }
1949  }
1950  /* "normal case": just update the activity */
1951  else
1952  {
1953  QUAD_ASSIGN(delta, newcontribution);
1954  SCIPquadprecSumQD(delta, delta, -oldcontribution);
1955  }
1956  }
1957 
1958  /* update the activity, if the current value is valid and there was a change in the finite part */
1959  if( validact && (QUAD_TO_DBL(delta) != 0.0) )
1960  {
1961  SCIP_Real curractivity;
1962 
1963  /* if the absolute value of the activity is increased, this is regarded as reliable,
1964  * otherwise, we check whether we can still trust the updated value
1965  */
1966  SCIPquadprecSumQD(*activity, *activity, QUAD_TO_DBL(delta));
1967 
1968  curractivity = QUAD_TO_DBL(*activity);
1969  assert(!SCIPisInfinity(scip, -curractivity) && !SCIPisInfinity(scip, curractivity));
1970 
1971  if( REALABS((*lastactivity)) < REALABS(curractivity) )
1972  {
1973  (*lastactivity) = curractivity;
1974  }
1975  else
1976  {
1977  if( checkreliability && SCIPisUpdateUnreliable(scip, curractivity, (*lastactivity)) )
1978  {
1979  SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1980  (global ? "global " : ""), curractivity);
1981 
1982  /* mark the activity that was just changed and is not reliable anymore to be invalid */
1983  if( global )
1984  {
1985  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1986  consdata->validglbminact = FALSE;
1987  else
1988  consdata->validglbmaxact = FALSE;
1989  }
1990  else
1991  {
1992  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1993  consdata->validminact = FALSE;
1994  else
1995  consdata->validmaxact = FALSE;
1996  }
1997  }
1998  }
1999  }
2000 }
2001 
2002 /** updates minimum and maximum activity for a change in lower bound */
2003 static
2005  SCIP* scip, /**< SCIP data structure */
2006  SCIP_CONSDATA* consdata, /**< linear constraint data */
2007  SCIP_VAR* var, /**< variable that has been changed */
2008  SCIP_Real oldlb, /**< old lower bound of variable */
2009  SCIP_Real newlb, /**< new lower bound of variable */
2010  SCIP_Real val, /**< coefficient of constraint entry */
2011  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2012  )
2013 {
2014  assert(scip != NULL);
2015  assert(consdata != NULL);
2016  assert(var != NULL);
2017 
2018  if( consdata->validactivities )
2019  {
2020  consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
2021 
2022  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2023  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2024  }
2025 }
2026 
2027 /** updates minimum and maximum activity for a change in upper bound */
2028 static
2030  SCIP* scip, /**< SCIP data structure */
2031  SCIP_CONSDATA* consdata, /**< linear constraint data */
2032  SCIP_VAR* var, /**< variable that has been changed */
2033  SCIP_Real oldub, /**< old upper bound of variable */
2034  SCIP_Real newub, /**< new upper bound of variable */
2035  SCIP_Real val, /**< coefficient of constraint entry */
2036  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2037  )
2038 {
2039  assert(scip != NULL);
2040  assert(consdata != NULL);
2041  assert(var != NULL);
2042 
2043  if( consdata->validactivities )
2044  {
2045  consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
2046 
2047  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2048  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2049  }
2050 }
2051 
2052 /** updates minimum and maximum global activity for a change in the global lower bound */
2053 static
2055  SCIP* scip, /**< SCIP data structure */
2056  SCIP_CONSDATA* consdata, /**< linear constraint data */
2057  SCIP_Real oldlb, /**< old lower bound of variable */
2058  SCIP_Real newlb, /**< new lower bound of variable */
2059  SCIP_Real val, /**< coefficient of constraint entry */
2060  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2061  )
2062 {
2063  assert(scip != NULL);
2064  assert(consdata != NULL);
2065 
2066  if( consdata->validactivities )
2067  {
2068  consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2069 
2070  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2071  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2072  }
2074 
2075 /** updates minimum and maximum global activity for a change in global upper bound */
2076 static
2078  SCIP* scip, /**< SCIP data structure */
2079  SCIP_CONSDATA* consdata, /**< linear constraint data */
2080  SCIP_Real oldub, /**< old upper bound of variable */
2081  SCIP_Real newub, /**< new upper bound of variable */
2082  SCIP_Real val, /**< coefficient of constraint entry */
2083  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2084  )
2085 {
2086  assert(scip != NULL);
2087  assert(consdata != NULL);
2088 
2089  if( consdata->validactivities )
2090  {
2091  consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2092 
2093  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2094  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2095  }
2097 
2098 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2099 static
2101  SCIP* scip, /**< SCIP data structure */
2102  SCIP_CONSDATA* consdata, /**< linear constraint data */
2103  SCIP_VAR* var, /**< variable of constraint entry */
2104  SCIP_Real val, /**< coefficient of constraint entry */
2105  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2106  )
2107 {
2108  assert(scip != NULL);
2109  assert(consdata != NULL);
2110  assert(var != NULL);
2111 
2112  /* update maximum absolute value */
2113  if( consdata->validmaxabsval )
2114  {
2115  SCIP_Real absval;
2116 
2117  assert(consdata->maxabsval < SCIP_INVALID);
2118 
2119  absval = REALABS(val);
2120  consdata->maxabsval = MAX(consdata->maxabsval, absval);
2121  }
2122 
2123  if( consdata->validminabsval )
2124  {
2125  SCIP_Real absval;
2126 
2127  assert(consdata->minabsval < SCIP_INVALID);
2128 
2129  absval = REALABS(val);
2130  consdata->minabsval = MIN(consdata->minabsval, absval);
2131  }
2132 
2133  /* update minimal and maximal activity */
2134  if( consdata->validactivities )
2135  {
2136  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2137  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2138  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2139  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2140 
2141  consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2142  consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2143  consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2144  consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2145  }
2146 }
2147 
2148 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2149 static
2151  SCIP* scip, /**< SCIP data structure */
2152  SCIP_CONSDATA* consdata, /**< linear constraint data */
2153  SCIP_VAR* var, /**< variable of constraint entry */
2154  SCIP_Real val, /**< coefficient of constraint entry */
2155  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2156  )
2157 {
2158  assert(scip != NULL);
2159  assert(consdata != NULL);
2160  assert(var != NULL);
2161 
2162  /* invalidate maximum absolute value, if this coefficient was the maximum */
2163  if( consdata->validmaxabsval )
2164  {
2165  SCIP_Real absval;
2166 
2167  absval = REALABS(val);
2168 
2169  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2170  {
2171  consdata->validmaxabsval = FALSE;
2172  consdata->maxabsval = SCIP_INVALID;
2173  }
2174  }
2175 
2176  /* invalidate minimum absolute value, if this coefficient was the minimum */
2177  if( consdata->validminabsval )
2178  {
2179  SCIP_Real absval;
2180 
2181  absval = REALABS(val);
2182 
2183  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2184  {
2185  consdata->validminabsval = FALSE;
2186  consdata->minabsval = SCIP_INVALID;
2187  }
2188  }
2189 
2190  /* update minimal and maximal activity */
2191  if( consdata->validactivities )
2192  {
2193  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2194  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2195  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2196  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2197 
2198  consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2199  consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2200  consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2201  consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2202  }
2203 }
2204 
2205 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2206 static
2208  SCIP* scip, /**< SCIP data structure */
2209  SCIP_CONSDATA* consdata, /**< linear constraint data */
2210  SCIP_VAR* var, /**< variable of constraint entry */
2211  SCIP_Real oldval, /**< old coefficient of constraint entry */
2212  SCIP_Real newval, /**< new coefficient of constraint entry */
2213  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2214  )
2215 {
2216  assert(scip != NULL);
2217  assert(consdata != NULL);
2218  assert(var != NULL);
2219 
2220  /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2221  assert(!SCIPisZero(scip, oldval));
2222 
2223  /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2224  assert(!SCIPisZero(scip, newval));
2225 
2226  /* update maximum absolute value */
2227  if( consdata->validmaxabsval )
2228  {
2229  SCIP_Real absval;
2230 
2231  absval = REALABS(newval);
2232 
2233  if( SCIPisGE(scip, absval, consdata->maxabsval) )
2234  {
2235  consdata->maxabsval = absval;
2236  }
2237  else
2238  {
2239  absval = REALABS(oldval);
2240 
2241  /* invalidate maximum absolute value */
2242  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2243  {
2244  consdata->validmaxabsval = FALSE;
2245  consdata->maxabsval = SCIP_INVALID;
2246  }
2247  }
2248  }
2249 
2250  /* update minimum absolute value */
2251  if( consdata->validminabsval )
2252  {
2253  SCIP_Real absval;
2254 
2255  absval = REALABS(newval);
2256 
2257  if( SCIPisLE(scip, absval, consdata->minabsval) )
2258  {
2259  consdata->minabsval = absval;
2260  }
2261  else
2262  {
2263  absval = REALABS(oldval);
2264 
2265  /* invalidate minimum absolute value */
2266  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2267  {
2268  consdata->validminabsval = FALSE;
2269  consdata->minabsval = SCIP_INVALID;
2270  }
2271  }
2272  }
2273 
2274  /* update maximum activity delta */
2275  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2276  {
2277  SCIP_Real domain;
2278  SCIP_Real delta;
2279 
2280  assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
2281  assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
2282 
2283  domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
2284  delta = REALABS(newval) * domain;
2285 
2286  if( delta > consdata->maxactdelta )
2287  {
2288  consdata->maxactdelta = delta;
2289  consdata->maxactdeltavar = var;
2290  }
2291  else
2292  {
2293  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2294  if( consdata->maxactdeltavar == var )
2295  consdata->maxactdelta = SCIP_INVALID;
2296  }
2297  }
2298 
2299  /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2300  consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2301  consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2302 }
2303 
2304 /** returns the maximum absolute value of all coefficients in the constraint */
2305 static
2307  SCIP_CONSDATA* consdata /**< linear constraint data */
2308  )
2309 {
2310  assert(consdata != NULL);
2311 
2312  if( !consdata->validmaxabsval )
2313  consdataCalcMaxAbsval(consdata);
2314  assert(consdata->validmaxabsval);
2315  assert(consdata->maxabsval < SCIP_INVALID);
2316 
2317  return consdata->maxabsval;
2318 }
2319 
2320 /** returns the minimum absolute value of all coefficients in the constraint */
2321 static
2323  SCIP_CONSDATA* consdata /**< linear constraint data */
2324  )
2326  assert(consdata != NULL);
2327 
2328  if( !consdata->validminabsval )
2329  consdataCalcMinAbsval(consdata);
2330  assert(consdata->validminabsval);
2331  assert(consdata->minabsval < SCIP_INVALID);
2332 
2333  return consdata->minabsval;
2334 }
2335 
2336 /** calculates minimum and maximum local and global activity for constraint from scratch;
2337  * additionally recalculates maximum absolute value of coefficients
2338  */
2339 static
2341  SCIP* scip, /**< SCIP data structure */
2342  SCIP_CONSDATA* consdata /**< linear constraint data */
2343  )
2344 {
2345  int i;
2346 
2347  assert(scip != NULL);
2348  assert(consdata != NULL);
2349  assert(!consdata->validactivities);
2350  assert(QUAD_TO_DBL(consdata->minactivity) >= SCIP_INVALID || consdata->validminact);
2351  assert(QUAD_TO_DBL(consdata->maxactivity) >= SCIP_INVALID || consdata->validmaxact);
2352  assert(QUAD_TO_DBL(consdata->glbminactivity) >= SCIP_INVALID || consdata->validglbminact);
2353  assert(QUAD_TO_DBL(consdata->glbmaxactivity) >= SCIP_INVALID || consdata->validglbmaxact);
2354 
2355  consdata->validmaxabsval = TRUE;
2356  consdata->validminabsval = TRUE;
2357  consdata->validactivities = TRUE;
2358  consdata->validminact = TRUE;
2359  consdata->validmaxact = TRUE;
2360  consdata->validglbminact = TRUE;
2361  consdata->validglbmaxact = TRUE;
2362  consdata->maxabsval = 0.0;
2363  consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2364  QUAD_ASSIGN(consdata->minactivity, 0.0);
2365  QUAD_ASSIGN(consdata->maxactivity, 0.0);
2366  consdata->lastminactivity = 0.0;
2367  consdata->lastmaxactivity = 0.0;
2368  consdata->minactivityneginf = 0;
2369  consdata->minactivityposinf = 0;
2370  consdata->maxactivityneginf = 0;
2371  consdata->maxactivityposinf = 0;
2372  consdata->minactivityneghuge = 0;
2373  consdata->minactivityposhuge = 0;
2374  consdata->maxactivityneghuge = 0;
2375  consdata->maxactivityposhuge = 0;
2376  QUAD_ASSIGN(consdata->glbminactivity, 0.0);
2377  QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
2378  consdata->lastglbminactivity = 0.0;
2379  consdata->lastglbmaxactivity = 0.0;
2380  consdata->glbminactivityneginf = 0;
2381  consdata->glbminactivityposinf = 0;
2382  consdata->glbmaxactivityneginf = 0;
2383  consdata->glbmaxactivityposinf = 0;
2384  consdata->glbminactivityneghuge = 0;
2385  consdata->glbminactivityposhuge = 0;
2386  consdata->glbmaxactivityneghuge = 0;
2387  consdata->glbmaxactivityposhuge = 0;
2388 
2389  for( i = 0; i < consdata->nvars; ++i )
2390  consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2391 
2392  consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
2393  consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
2394  consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
2395  consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2396 }
2397 
2398 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2399  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2400  */
2401 static
2402 void getMinActivity(
2403  SCIP* scip, /**< SCIP data structure */
2404  SCIP_CONSDATA* consdata, /**< linear constraint */
2405  int posinf, /**< number of coefficients contributing pos. infinite value */
2406  int neginf, /**< number of coefficients contributing neg. infinite value */
2407  int poshuge, /**< number of coefficients contributing huge pos. value */
2408  int neghuge, /**< number of coefficients contributing huge neg. value */
2409  SCIP_Real delta, /**< value to subtract from stored minactivity
2410  * (contribution of the variable set to zero when getting residual activity) */
2411  SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2412  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2413  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2414  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2415  * i.e. is <= the exact minactivity (in case of huge contributing values) */
2416  SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2417  )
2418 {
2419  assert(scip != NULL);
2420  assert(consdata != NULL);
2421  assert(posinf >= 0);
2422  assert(neginf >= 0);
2423  assert(poshuge >= 0);
2424  assert(neghuge >= 0);
2425  assert(minactivity != NULL);
2426  assert(isrelax != NULL);
2427  assert(issettoinfinity != NULL);
2428 
2429  /* if we have pos. infinite contributions, the minactivity is +infty */
2430  if( posinf > 0 )
2431  {
2432  *minactivity = SCIPinfinity(scip);
2433  *issettoinfinity = TRUE;
2434  *isrelax = FALSE;
2435  }
2436  /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2437  else if( neginf > 0 )
2438  {
2439  *minactivity = -SCIPinfinity(scip);
2440  *issettoinfinity = TRUE;
2441  *isrelax = FALSE;
2442  }
2443  /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2444  else if( neghuge > 0 )
2445  {
2446  *minactivity = -SCIPinfinity(scip);
2447  *issettoinfinity = TRUE;
2448  *isrelax = TRUE;
2449  }
2450  /* we do not need a good relaxation and we have positive huge contributions, so we just return -infty as activity */
2451  else if( !goodrelax && poshuge > 0 )
2452  {
2453  *minactivity = -SCIPinfinity(scip);
2454  *issettoinfinity = TRUE;
2455  *isrelax = TRUE;
2456  }
2457  else
2458  {
2459  SCIP_Real tmpactivity;
2460 
2461  /* recompute minactivity if it is not valid */
2462  if( global )
2463  {
2464  if( !consdata->validglbminact )
2465  consdataRecomputeGlbMinactivity(scip, consdata);
2466  assert(consdata->validglbminact);
2467 
2468  tmpactivity = QUAD_TO_DBL(consdata->glbminactivity);
2469  }
2470  else
2471  {
2472  if( !consdata->validminact )
2473  consdataRecomputeMinactivity(scip, consdata);
2474  assert(consdata->validminact);
2475 
2476  tmpactivity = QUAD_TO_DBL(consdata->minactivity);
2477  }
2478 
2479  /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2480  * a feasible relaxation of the minactivity is the number of positive huge contributions
2481  * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2482  */
2483  if( poshuge > 0 )
2484  {
2485  *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2486  *issettoinfinity = FALSE;
2487  *isrelax = TRUE;
2488  }
2489  /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2490  else
2491  {
2492  *minactivity = tmpactivity - delta;
2493  *issettoinfinity = FALSE;
2494  *isrelax = FALSE;
2495  }
2496  }
2497 }
2498 
2499 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2500  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2501  */
2502 static
2503 void getMaxActivity(
2504  SCIP* scip, /**< SCIP data structure */
2505  SCIP_CONSDATA* consdata, /**< linear constraint */
2506  int posinf, /**< number of coefficients contributing pos. infinite value */
2507  int neginf, /**< number of coefficients contributing neg. infinite value */
2508  int poshuge, /**< number of coefficients contributing huge pos. value */
2509  int neghuge, /**< number of coefficients contributing huge neg. value */
2510  SCIP_Real delta, /**< value to subtract from stored maxactivity
2511  * (contribution of the variable set to zero when getting residual activity) */
2512  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2513  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2514  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2515  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2516  * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2517  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2518  )
2519 {
2520  assert(scip != NULL);
2521  assert(consdata != NULL);
2522  assert(posinf >= 0);
2523  assert(neginf >= 0);
2524  assert(poshuge >= 0);
2525  assert(neghuge >= 0);
2526  assert(maxactivity != NULL);
2527  assert(isrelax != NULL);
2528  assert(issettoinfinity != NULL);
2529 
2530  /* if we have neg. infinite contributions, the maxactivity is -infty */
2531  if( neginf > 0 )
2532  {
2533  *maxactivity = -SCIPinfinity(scip);
2534  *issettoinfinity = TRUE;
2535  *isrelax = FALSE;
2536  }
2537  /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2538  else if( posinf > 0 )
2539  {
2540  *maxactivity = SCIPinfinity(scip);
2541  *issettoinfinity = TRUE;
2542  *isrelax = FALSE;
2543  }
2544  /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2545  else if( poshuge > 0 )
2546  {
2547  *maxactivity = SCIPinfinity(scip);
2548  *issettoinfinity = TRUE;
2549  *isrelax = TRUE;
2550  }
2551  /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2552  else if( !goodrelax && neghuge > 0 )
2553  {
2554  *maxactivity = SCIPinfinity(scip);
2555  *issettoinfinity = TRUE;
2556  *isrelax = TRUE;
2557  }
2558  else
2559  {
2560  SCIP_Real tmpactivity;
2561 
2562  /* recompute maxactivity if it is not valid */
2563  if( global )
2564  {
2565  if( !consdata->validglbmaxact )
2566  consdataRecomputeGlbMaxactivity(scip, consdata);
2567  assert(consdata->validglbmaxact);
2568 
2569  tmpactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2570  }
2571  else
2572  {
2573  if( !consdata->validmaxact )
2574  consdataRecomputeMaxactivity(scip, consdata);
2575  assert(consdata->validmaxact);
2576 
2577  tmpactivity = QUAD_TO_DBL(consdata->maxactivity);
2578  }
2579 
2580  /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2581  * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2582  * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2583  */
2584  if( neghuge > 0 )
2585  {
2586  *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2587  *issettoinfinity = FALSE;
2588  *isrelax = TRUE;
2589  }
2590  /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2591  else
2592  {
2593  *maxactivity = tmpactivity - delta;
2594  *issettoinfinity = FALSE;
2595  *isrelax = FALSE;
2596  }
2597  }
2598 }
2599 
2600 /** gets activity bounds for constraint */
2601 static
2603  SCIP* scip, /**< SCIP data structure */
2604  SCIP_CONSDATA* consdata, /**< linear constraint */
2605  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2606  * relaxed activities ignored, anyway? */
2607  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2608  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2609  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2610  * i.e. <= the exact minactivity (in case of huge contributions),
2611  * or equal to the exact minimal activity */
2612  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2613  * i.e. >= the exact maxactivity (in case of huge contributions),
2614  * or equal to the exact maximal activity */
2615  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2616  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2617 
2618  )
2619 {
2620  assert(scip != NULL);
2621  assert(consdata != NULL);
2622  assert(minactivity != NULL);
2623  assert(maxactivity != NULL);
2624  assert(isminsettoinfinity != NULL);
2625  assert(ismaxsettoinfinity != NULL);
2626 
2627  if( !consdata->validactivities )
2628  {
2629  consdataCalcActivities(scip, consdata);
2630  assert(consdata->validminact);
2631  assert(consdata->validmaxact);
2632  }
2633  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2634  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2635  assert(consdata->minactivityneginf >= 0);
2636  assert(consdata->minactivityposinf >= 0);
2637  assert(consdata->maxactivityneginf >= 0);
2638  assert(consdata->maxactivityposinf >= 0);
2639 
2640  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2641  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2642  minactivity, minisrelax, isminsettoinfinity);
2643 
2644  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2645  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2646  maxactivity, maxisrelax, ismaxsettoinfinity);
2647 }
2648 
2649 /** calculates activity bounds for constraint after setting variable to zero */
2650 static
2652  SCIP* scip, /**< SCIP data structure */
2653  SCIP_CONSDATA* consdata, /**< linear constraint */
2654  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2655  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2656  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2657  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2658  )
2659 {
2660  SCIP_VAR* var;
2661  SCIP_Real val;
2662  SCIP_Real lb;
2663  SCIP_Real ub;
2664  int v;
2665 
2666  assert(scip != NULL);
2667  assert(consdata != NULL);
2668  assert(cancelvar != NULL);
2669  assert(resactivity != NULL);
2671  *resactivity = 0.0;
2672 
2673  for( v = 0; v < consdata->nvars; ++v )
2674  {
2675  var = consdata->vars[v];
2676  assert(var != NULL);
2677  if( var == cancelvar )
2678  continue;
2679 
2680  val = consdata->vals[v];
2681 
2682  if( useglobalbounds )
2683  {
2684  lb = SCIPvarGetLbGlobal(var);
2685  ub = SCIPvarGetUbGlobal(var);
2686  }
2687  else
2688  {
2689  lb = SCIPvarGetLbLocal(var);
2690  ub = SCIPvarGetUbLocal(var);
2691  }
2692 
2693  assert(!SCIPisZero(scip, val));
2694  assert(SCIPisLE(scip, lb, ub));
2695 
2696  if( val > 0.0 )
2697  {
2698  if( isminresact )
2699  {
2700  assert(!SCIPisInfinity(scip, -lb));
2701  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2702  *resactivity += val*lb;
2703  }
2704  else
2705  {
2706  assert(!SCIPisInfinity(scip, ub));
2707  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2708  *resactivity += val*ub;
2709  }
2710  }
2711  else
2712  {
2713  if( isminresact)
2714  {
2715  assert(!SCIPisInfinity(scip, ub));
2716  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2717  *resactivity += val*ub;
2718  }
2719  else
2720  {
2721  assert(!SCIPisInfinity(scip, -lb));
2722  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2723  *resactivity += val*lb;
2724  }
2725  }
2726  }
2727  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2728 }
2729 
2730 /** gets activity bounds for constraint after setting variable to zero */
2731 static
2733  SCIP* scip, /**< SCIP data structure */
2734  SCIP_CONSDATA* consdata, /**< linear constraint */
2735  SCIP_VAR* var, /**< variable to calculate activity residual for */
2736  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2737  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2738  * relaxed acticities ignored, anyway? */
2739  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2740  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2741  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2742  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2743  * contributions), or equal to the exact residual minactivity */
2744  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2745  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2746  * contributions), or equal to the exact residual minactivity */
2747  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2748  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2749  )
2750 {
2751  SCIP_Real minactbound;
2752  SCIP_Real maxactbound;
2753  SCIP_Real absval;
2754 
2755  assert(scip != NULL);
2756  assert(consdata != NULL);
2757  assert(var != NULL);
2758  assert(minresactivity != NULL);
2759  assert(maxresactivity != NULL);
2760  assert(minisrelax != NULL);
2761  assert(maxisrelax != NULL);
2762  assert(isminsettoinfinity != NULL);
2763  assert(ismaxsettoinfinity != NULL);
2764 
2765  /* get activity bounds of linear constraint */
2766  if( !consdata->validactivities )
2767  {
2768  consdataCalcActivities(scip, consdata);
2769  assert(consdata->validminact);
2770  assert(consdata->validmaxact);
2771  }
2772  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2773  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2774  assert(consdata->minactivityneginf >= 0);
2775  assert(consdata->minactivityposinf >= 0);
2776  assert(consdata->maxactivityneginf >= 0);
2777  assert(consdata->maxactivityposinf >= 0);
2778  assert(consdata->minactivityneghuge >= 0);
2779  assert(consdata->minactivityposhuge >= 0);
2780  assert(consdata->maxactivityneghuge >= 0);
2781  assert(consdata->maxactivityposhuge >= 0);
2782 
2783  if( val > 0.0 )
2784  {
2785  minactbound = SCIPvarGetLbLocal(var);
2786  maxactbound = SCIPvarGetUbLocal(var);
2787  absval = val;
2788  }
2789  else
2790  {
2791  minactbound = -SCIPvarGetUbLocal(var);
2792  maxactbound = -SCIPvarGetLbLocal(var);
2793  absval = -val;
2794  }
2795 
2796  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2797  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2798  */
2799  if( SCIPisInfinity(scip, minactbound) )
2800  {
2801  assert(consdata->minactivityposinf >= 1);
2802 
2803  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2804  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2805  minresactivity, minisrelax, isminsettoinfinity);
2806  }
2807  else if( SCIPisInfinity(scip, -minactbound) )
2808  {
2809  assert(consdata->minactivityneginf >= 1);
2810 
2811  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2812  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2813  minresactivity, minisrelax, isminsettoinfinity);
2814  }
2815  else if( SCIPisHugeValue(scip, minactbound * absval) )
2816  {
2817  assert(consdata->minactivityposhuge >= 1);
2818 
2819  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2820  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2821  minresactivity, minisrelax, isminsettoinfinity);
2822  }
2823  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2824  {
2825  assert(consdata->minactivityneghuge >= 1);
2826 
2827  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2828  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2829  minresactivity, minisrelax, isminsettoinfinity);
2830  }
2831  else
2832  {
2833  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2834  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2835  minresactivity, minisrelax, isminsettoinfinity);
2836  }
2837 
2838  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2839  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2840  */
2841  if( SCIPisInfinity(scip, -maxactbound) )
2842  {
2843  assert(consdata->maxactivityneginf >= 1);
2844 
2845  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2846  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2847  maxresactivity, maxisrelax, ismaxsettoinfinity);
2848  }
2849  else if( SCIPisInfinity(scip, maxactbound) )
2850  {
2851  assert(consdata->maxactivityposinf >= 1);
2852 
2853  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2854  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2855  maxresactivity, maxisrelax, ismaxsettoinfinity);
2856  }
2857  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2858  {
2859  assert(consdata->maxactivityposhuge >= 1);
2860 
2861  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2862  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2863  maxresactivity, maxisrelax, ismaxsettoinfinity);
2864  }
2865  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2866  {
2867  assert(consdata->maxactivityneghuge >= 1);
2868 
2869  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2870  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2871  maxresactivity, maxisrelax, ismaxsettoinfinity);
2872  }
2873  else
2874  {
2875  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2876  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2877  maxresactivity, maxisrelax, ismaxsettoinfinity);
2878  }
2879 }
2880 
2881 /** gets global activity bounds for constraint */
2882 static
2884  SCIP* scip, /**< SCIP data structure */
2885  SCIP_CONSDATA* consdata, /**< linear constraint */
2886  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2887  * relaxed acticities ignored, anyway? */
2888  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2889  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2890  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2891  * i.e. <= the exact minactivity (in case of huge contributions),
2892  * or equal to the exact minimal activity */
2893  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2894  * i.e. >= the exact maxactivity (in case of huge contributions),
2895  * or equal to the exact maximal activity */
2896  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2897  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2898  )
2899 {
2900  assert(scip != NULL);
2901  assert(consdata != NULL);
2902  assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2903  || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2904 
2905  if( !consdata->validactivities )
2906  {
2907  consdataCalcActivities(scip, consdata);
2908  assert(consdata->validglbminact);
2909  assert(consdata->validglbmaxact);
2910  }
2911  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2912  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2913  assert(consdata->glbminactivityneginf >= 0);
2914  assert(consdata->glbminactivityposinf >= 0);
2915  assert(consdata->glbmaxactivityneginf >= 0);
2916  assert(consdata->glbmaxactivityposinf >= 0);
2917  assert(consdata->glbminactivityneghuge >= 0);
2918  assert(consdata->glbminactivityposhuge >= 0);
2919  assert(consdata->glbmaxactivityneghuge >= 0);
2920  assert(consdata->glbmaxactivityposhuge >= 0);
2921 
2922  if( glbminactivity != NULL )
2923  {
2924  assert(isminsettoinfinity != NULL);
2925  assert(minisrelax != NULL);
2926 
2927  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2928  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2929  glbminactivity, minisrelax, isminsettoinfinity);
2930  }
2931 
2932  if( glbmaxactivity != NULL )
2933  {
2934  assert(ismaxsettoinfinity != NULL);
2935  assert(maxisrelax != NULL);
2936 
2937  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2938  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2939  glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2940  }
2941 }
2942 
2943 /** gets global activity bounds for constraint after setting variable to zero */
2944 static
2946  SCIP* scip, /**< SCIP data structure */
2947  SCIP_CONSDATA* consdata, /**< linear constraint */
2948  SCIP_VAR* var, /**< variable to calculate activity residual for */
2949  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2950  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2951  * relaxed acticities ignored, anyway? */
2952  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2953  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2954  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2955  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2956  * contributions), or equal to the exact residual minactivity */
2957  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2958  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2959  * contributions), or equal to the exact residual minactivity */
2960  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2961  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2962  )
2963 {
2964  SCIP_Real minactbound;
2965  SCIP_Real maxactbound;
2966  SCIP_Real absval;
2967 
2968  assert(scip != NULL);
2969  assert(consdata != NULL);
2970  assert(var != NULL);
2971  assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2972  || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2973 
2974  /* get activity bounds of linear constraint */
2975  if( !consdata->validactivities )
2976  consdataCalcActivities(scip, consdata);
2977 
2978  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2979  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2980  assert(consdata->glbminactivityneginf >= 0);
2981  assert(consdata->glbminactivityposinf >= 0);
2982  assert(consdata->glbmaxactivityneginf >= 0);
2983  assert(consdata->glbmaxactivityposinf >= 0);
2984 
2985  if( val > 0.0 )
2986  {
2987  minactbound = SCIPvarGetLbGlobal(var);
2988  maxactbound = SCIPvarGetUbGlobal(var);
2989  absval = val;
2990  }
2991  else
2992  {
2993  minactbound = -SCIPvarGetUbGlobal(var);
2994  maxactbound = -SCIPvarGetLbGlobal(var);
2995  absval = -val;
2996  }
2997 
2998  if( minresactivity != NULL )
2999  {
3000  assert(isminsettoinfinity != NULL);
3001  assert(minisrelax != NULL);
3002 
3003  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
3004  * and contribution of variable set to zero that has to be subtracted from finite part of activity
3005  */
3006  if( SCIPisInfinity(scip, minactbound) )
3007  {
3008  assert(consdata->glbminactivityposinf >= 1);
3009 
3010  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
3011  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3012  minresactivity, minisrelax, isminsettoinfinity);
3013  }
3014  else if( SCIPisInfinity(scip, -minactbound) )
3015  {
3016  assert(consdata->glbminactivityneginf >= 1);
3017 
3018  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
3019  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3020  minresactivity, minisrelax, isminsettoinfinity);
3021  }
3022  else if( SCIPisHugeValue(scip, minactbound * absval) )
3023  {
3024  assert(consdata->glbminactivityposhuge >= 1);
3025 
3026  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3027  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3028  minresactivity, minisrelax, isminsettoinfinity);
3029  }
3030  else if( SCIPisHugeValue(scip, -minactbound * absval) )
3031  {
3032  assert(consdata->glbminactivityneghuge >= 1);
3033 
3034  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3035  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
3036  minresactivity, minisrelax, isminsettoinfinity);
3037  }
3038  else
3039  {
3040  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3041  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
3042  goodrelax, minresactivity, minisrelax, isminsettoinfinity);
3043  }
3044  }
3045 
3046  if( maxresactivity != NULL )
3047  {
3048  assert(ismaxsettoinfinity != NULL);
3049  assert(maxisrelax != NULL);
3050 
3051  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
3052  * and contribution of variable set to zero that has to be subtracted from finite part of activity
3053  */
3054  if( SCIPisInfinity(scip, -maxactbound) )
3055  {
3056  assert(consdata->glbmaxactivityneginf >= 1);
3057 
3058  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
3059  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3060  maxresactivity, maxisrelax, ismaxsettoinfinity);
3061  }
3062  else if( SCIPisInfinity(scip, maxactbound) )
3063  {
3064  assert(consdata->glbmaxactivityposinf >= 1);
3065 
3066  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
3067  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3068  maxresactivity, maxisrelax, ismaxsettoinfinity);
3069  }
3070  else if( SCIPisHugeValue(scip, absval * maxactbound) )
3071  {
3072  assert(consdata->glbmaxactivityposhuge >= 1);
3073 
3074  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3075  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3076  maxresactivity, maxisrelax, ismaxsettoinfinity);
3077  }
3078  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3079  {
3080  assert(consdata->glbmaxactivityneghuge >= 1);
3081 
3082  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3083  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3084  maxresactivity, maxisrelax, ismaxsettoinfinity);
3085  }
3086  else
3087  {
3088  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3089  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3090  goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
3091  }
3092  }
3093 }
3094 
3095 /** calculates the activity of the linear constraint for given solution */
3096 static
3098  SCIP* scip, /**< SCIP data structure */
3099  SCIP_CONSDATA* consdata, /**< linear constraint data */
3100  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3101  )
3102 {
3103  SCIP_Real activity;
3104 
3105  assert(scip != NULL);
3106  assert(consdata != NULL);
3107 
3108  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3109  activity = consdataComputePseudoActivity(scip, consdata);
3110  else
3111  {
3112  SCIP_Real solval;
3113  int nposinf;
3114  int nneginf;
3115  SCIP_Bool negsign;
3116  int v;
3117 
3118  activity = 0.0;
3119  nposinf = 0;
3120  nneginf = 0;
3121 
3122  for( v = 0; v < consdata->nvars; ++v )
3123  {
3124  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3125 
3126  if( consdata->vals[v] < 0 )
3127  negsign = TRUE;
3128  else
3129  negsign = FALSE;
3130 
3131  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3132  ++nposinf;
3133  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3134  ++nneginf;
3135  else
3136  activity += consdata->vals[v] * solval;
3137  }
3138  assert(nneginf >= 0 && nposinf >= 0);
3139 
3140  SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3141 
3142  /* check for amount of infinity values and correct the activity */
3143  if( nposinf > 0 && nneginf > 0 )
3144  activity = (consdata->rhs + consdata->lhs) / 2;
3145  else if( nposinf > 0 )
3146  activity = SCIPinfinity(scip);
3147  else if( nneginf > 0 )
3148  activity = -SCIPinfinity(scip);
3149 
3150  SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3151  }
3152 
3153  if( activity == SCIP_INVALID ) /*lint !e777*/
3154  return activity;
3155  else if( activity < 0 )
3156  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3157  else
3158  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3159 
3160  return activity;
3161 }
3162 
3163 /** calculates the feasibility of the linear constraint for given solution */
3164 static
3166  SCIP* scip, /**< SCIP data structure */
3167  SCIP_CONSDATA* consdata, /**< linear constraint data */
3168  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3169  )
3170 {
3171  SCIP_Real activity;
3172 
3173  assert(scip != NULL);
3174  assert(consdata != NULL);
3175 
3176  activity = consdataGetActivity(scip, consdata, sol);
3177 
3178  if( activity == SCIP_INVALID ) /*lint !e777*/
3179  return -SCIPinfinity(scip);
3180 
3181  return MIN(consdata->rhs - activity, activity - consdata->lhs);
3182 }
3183 
3184 /** updates bit signatures after adding a single coefficient */
3185 static
3187  SCIP_CONSDATA* consdata, /**< linear constraint data */
3188  int pos /**< position of coefficient to update signatures for */
3189  )
3190 {
3191  uint64_t varsignature;
3192  SCIP_Real lb;
3193  SCIP_Real ub;
3194  SCIP_Real val;
3195 
3196  assert(consdata != NULL);
3197  assert(consdata->validsignature);
3198 
3199  varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3200  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3201  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3202  val = consdata->vals[pos];
3203  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3204  consdata->possignature |= varsignature;
3205  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3206  consdata->negsignature |= varsignature;
3207 }
3208 
3209 /** calculates the bit signatures of the given constraint data */
3210 static
3212  SCIP_CONSDATA* consdata /**< linear constraint data */
3213  )
3214 {
3215  assert(consdata != NULL);
3216 
3217  if( !consdata->validsignature )
3218  {
3219  int i;
3220 
3221  consdata->validsignature = TRUE;
3222  consdata->possignature = 0;
3223  consdata->negsignature = 0;
3224  for( i = 0; i < consdata->nvars; ++i )
3225  consdataUpdateSignatures(consdata, i);
3226  }
3227 }
3228 
3229 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3230 static
3231 SCIP_DECL_SORTINDCOMP(consdataCompVar)
3232 { /*lint --e{715}*/
3233  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3234  SCIP_VAR* var1;
3235  SCIP_VAR* var2;
3236 
3237  assert(consdata != NULL);
3238  assert(0 <= ind1 && ind1 < consdata->nvars);
3239  assert(0 <= ind2 && ind2 < consdata->nvars);
3240 
3241  var1 = consdata->vars[ind1];
3242  var2 = consdata->vars[ind2];
3243 
3244  /* exactly one variable is binary */
3245  if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3246  {
3247  return (SCIPvarIsBinary(var1) ? -1 : +1);
3248  }
3249  /* both variables are binary */
3250  else if( SCIPvarIsBinary(var1) )
3251  {
3252  return SCIPvarCompare(var1, var2);
3253  }
3254  else
3255  {
3256  SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3257  SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3258 
3259  if( vartype1 < vartype2 )
3260  return -1;
3261  else if( vartype1 > vartype2 )
3262  return +1;
3263  else
3264  return SCIPvarCompare(var1, var2);
3265  }
3266 }
3267 
3268 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3269 static
3270 SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
3271 { /*lint --e{715}*/
3272  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3273  SCIP_VAR* var1;
3274  SCIP_VAR* var2;
3275 
3276  assert(consdata != NULL);
3277  assert(0 <= ind1 && ind1 < consdata->nvars);
3278  assert(0 <= ind2 && ind2 < consdata->nvars);
3279 
3280  var1 = consdata->vars[ind1];
3281  var2 = consdata->vars[ind2];
3282 
3283  /* exactly one variable is binary */
3284  if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3285  {
3286  return (SCIPvarIsBinary(var1) ? -1 : +1);
3287  }
3288  /* both variables are binary */
3289  else if( SCIPvarIsBinary(var1) )
3290  {
3291  SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3292  SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3293 
3294  if( EPSGT(abscoef1, abscoef2, 1e-9) )
3295  return -1;
3296  else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3297  return +1;
3298  else
3299  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3300  }
3301  else
3302  {
3303  SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3304  SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3305 
3306  if( vartype1 < vartype2 )
3307  {
3308  return -1;
3309  }
3310  else if( vartype1 > vartype2 )
3311  {
3312  return +1;
3313  }
3314  else
3315  {
3316  /* both variables are continuous */
3317  if( !SCIPvarIsIntegral(var1) )
3318  {
3319  assert(!SCIPvarIsIntegral(var2));
3320  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3321  }
3322  else
3323  {
3324  SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3325  SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3326 
3327  if( EPSGT(abscont1, abscont2, 1e-9) )
3328  return -1;
3329  else if( EPSGT(abscont2, abscont1, 1e-9) )
3330  return +1;
3331  else
3332  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3333  }
3334  }
3335  }
3336 }
3337 
3338 /** permutes the constraint's variables according to a given permutation. */
3339 static
3340 void permSortConsdata(
3341  SCIP_CONSDATA* consdata, /**< the constraint data */
3342  int* perm, /**< the target permutation */
3343  int nvars /**< the number of variables */
3344  )
3345 { /*lint --e{715}*/
3346  SCIP_VAR* varv;
3347  SCIP_EVENTDATA* eventdatav;
3348  SCIP_Real valv;
3349  int v;
3350  int i;
3351  int nexti;
3352 
3353  assert(perm != NULL);
3354  assert(consdata != NULL);
3355 
3356  /* permute the variables in the linear constraint according to the target permutation */
3357  eventdatav = NULL;
3358  for( v = 0; v < nvars; ++v )
3359  {
3360  if( perm[v] != v )
3361  {
3362  varv = consdata->vars[v];
3363  valv = consdata->vals[v];
3364  if( consdata->eventdata != NULL )
3365  eventdatav = consdata->eventdata[v];
3366  i = v;
3367  do
3368  {
3369  assert(0 <= perm[i] && perm[i] < nvars);
3370  assert(perm[i] != i);
3371  consdata->vars[i] = consdata->vars[perm[i]];
3372  consdata->vals[i] = consdata->vals[perm[i]];
3373  if( consdata->eventdata != NULL )
3374  {
3375  consdata->eventdata[i] = consdata->eventdata[perm[i]];
3376  consdata->eventdata[i]->varpos = i;
3377  }
3378  nexti = perm[i];
3379  perm[i] = i;
3380  i = nexti;
3381  }
3382  while( perm[i] != v );
3383  consdata->vars[i] = varv;
3384  consdata->vals[i] = valv;
3385  if( consdata->eventdata != NULL )
3386  {
3387  consdata->eventdata[i] = eventdatav;
3388  consdata->eventdata[i]->varpos = i;
3389  }
3390  perm[i] = i;
3391  }
3392  }
3393 #ifdef SCIP_DEBUG
3394  /* check sorting */
3395  for( v = 0; v < nvars; ++v )
3396  {
3397  assert(perm[v] == v);
3398  assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3399  }
3400 #endif
3401 }
3402 
3403 /** sorts linear constraint's variables depending on the stage of the solving process:
3404  * - during PRESOLVING
3405  * sorts variables by binaries, integers, implicit integers, and continuous variables,
3406  * and the variables of the same type by non-decreasing variable index
3407  *
3408  * - during SOLVING
3409  * sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables,
3410  * and binary and integer variables by their global max activity delta (within each group),
3411  * ties within a group are broken by problem index of the variable.
3412  *
3413  * This fastens the propagation time of the constraint handler.
3414  */
3415 static
3417  SCIP* scip, /**< SCIP data structure */
3418  SCIP_CONSDATA* consdata /**< linear constraint data */
3419  )
3420 {
3421  assert(scip != NULL);
3422  assert(consdata != NULL);
3423 
3424  /* check if there are variables for sorting */
3425  if( consdata->nvars <= 1 )
3426  {
3427  consdata->indexsorted = TRUE;
3428  consdata->coefsorted = TRUE;
3429  consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3430  }
3431  else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3432  || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3433  {
3434  int* perm;
3435  int v;
3436 
3437  /* get temporary memory to store the sorted permutation */
3438  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3439 
3440  /* call sorting method */
3441  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
3442  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3443  else
3444  SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3445 
3446  permSortConsdata(consdata, perm, consdata->nvars);
3447 
3448  /* free temporary memory */
3449  SCIPfreeBufferArray(scip, &perm);
3450 
3451  if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE )
3452  {
3453  consdata->indexsorted = FALSE;
3454  consdata->coefsorted = TRUE;
3455 
3456  /* count binary variables in the sorted vars array */
3457  consdata->nbinvars = 0;
3458  for( v = 0; v < consdata->nvars; ++v )
3459  {
3460  if( SCIPvarIsBinary(consdata->vars[v]) )
3461  ++consdata->nbinvars;
3462  else
3463  break;
3464  }
3465  }
3466  else
3467  {
3468  consdata->indexsorted = TRUE;
3469  consdata->coefsorted = FALSE;
3470  }
3471  }
3472 
3473  return SCIP_OKAY;
3474 }
3475 
3476 
3477 /*
3478  * local linear constraint handler methods
3479  */
3480 
3481 /** sets left hand side of linear constraint */
3482 static
3484  SCIP* scip, /**< SCIP data structure */
3485  SCIP_CONS* cons, /**< linear constraint */
3486  SCIP_Real lhs /**< new left hand side */
3487  )
3488 {
3489  SCIP_CONSDATA* consdata;
3490  SCIP_Bool locked;
3491  int i;
3492 
3493  assert(scip != NULL);
3494  assert(cons != NULL);
3495  assert(!SCIPisInfinity(scip, lhs));
3496 
3497  /* adjust value to not be smaller than -inf */
3498  if ( SCIPisInfinity(scip, -lhs) )
3499  lhs = -SCIPinfinity(scip);
3500 
3501  consdata = SCIPconsGetData(cons);
3502  assert(consdata != NULL);
3503  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3504  assert(!SCIPisInfinity(scip, consdata->lhs));
3505 
3506  /* check whether the side is not changed */
3507  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3508  return SCIP_OKAY;
3509 
3510  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3511  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3512  {
3513  consdata->rhs = lhs;
3514  assert(consdata->row == NULL);
3515  }
3516 
3517  locked = FALSE;
3518  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3519  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3520 
3521  /* if necessary, update the rounding locks of variables */
3522  if( locked )
3523  {
3524  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3525  {
3526  SCIP_VAR** vars;
3527  SCIP_Real* vals;
3528  int v;
3529 
3530  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3531  vars = consdata->vars;
3532  vals = consdata->vals;
3533 
3534  for( v = 0; v < consdata->nvars; ++v )
3535  {
3536  assert(vars[v] != NULL);
3537  assert(!SCIPisZero(scip, vals[v]));
3538 
3539  if( SCIPisPositive(scip, vals[v]) )
3540  {
3541  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3542  }
3543  else
3544  {
3545  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3546  }
3547  }
3548  }
3549  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3550  {
3551  SCIP_VAR** vars;
3552  SCIP_Real* vals;
3553  int v;
3554 
3555  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3556  vars = consdata->vars;
3557  vals = consdata->vals;
3558 
3559  for( v = 0; v < consdata->nvars; ++v )
3560  {
3561  assert(vars[v] != NULL);
3562  assert(!SCIPisZero(scip, vals[v]));
3563 
3564  if( SCIPisPositive(scip, vals[v]) )
3565  {
3566  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3567  }
3568  else
3569  {
3570  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3571  }
3572  }
3573  }
3574  }
3575 
3576  /* 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 */
3577  if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3578  {
3579  consdata->boundstightened = 0;
3580  consdata->presolved = FALSE;
3581  consdata->cliquesadded = FALSE;
3582  consdata->implsadded = FALSE;
3583 
3584  /* mark the constraint for propagation */
3585  if( SCIPconsIsTransformed(cons) )
3586  {
3587  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3588  }
3589  }
3590 
3591  /* set new left hand side and update constraint data */
3592  consdata->lhs = lhs;
3593  consdata->changed = TRUE;
3594  consdata->normalized = FALSE;
3595  consdata->upgradetried = FALSE;
3596  consdata->rangedrowpropagated = 0;
3597 
3598  /* update the lhs of the LP row */
3599  if( consdata->row != NULL )
3600  {
3601  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3602  }
3603 
3604  return SCIP_OKAY;
3605 }
3606 
3607 /** sets right hand side of linear constraint */
3608 static
3610  SCIP* scip, /**< SCIP data structure */
3611  SCIP_CONS* cons, /**< linear constraint */
3612  SCIP_Real rhs /**< new right hand side */
3613  )
3614 {
3615  SCIP_CONSDATA* consdata;
3616  SCIP_Bool locked;
3617  int i;
3618 
3619  assert(scip != NULL);
3620  assert(cons != NULL);
3621  assert(!SCIPisInfinity(scip, -rhs));
3622 
3623  /* adjust value to not be larger than inf */
3624  if ( SCIPisInfinity(scip, rhs) )
3625  rhs = SCIPinfinity(scip);
3626 
3627  consdata = SCIPconsGetData(cons);
3628  assert(consdata != NULL);
3629  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3630  assert(!SCIPisInfinity(scip, -consdata->rhs));
3631 
3632  /* check whether the side is not changed */
3633  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3634  return SCIP_OKAY;
3635 
3636  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3637  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3638  {
3639  consdata->lhs = rhs;
3640  assert(consdata->row == NULL);
3641  }
3642 
3643  locked = FALSE;
3644  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3645  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3646 
3647  /* if necessary, update the rounding locks of variables */
3648  if( locked )
3649  {
3650  assert(SCIPconsIsTransformed(cons));
3651 
3652  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3653  {
3654  SCIP_VAR** vars;
3655  SCIP_Real* vals;
3656  int v;
3657 
3658  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3659  vars = consdata->vars;
3660  vals = consdata->vals;
3661 
3662  for( v = 0; v < consdata->nvars; ++v )
3663  {
3664  assert(vars[v] != NULL);
3665  assert(!SCIPisZero(scip, vals[v]));
3666 
3667  if( SCIPisPositive(scip, vals[v]) )
3668  {
3669  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3670  }
3671  else
3672  {
3673  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3674  }
3675  }
3676  }
3677  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3678  {
3679  SCIP_VAR** vars;
3680  SCIP_Real* vals;
3681  int v;
3682 
3683  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3684  vars = consdata->vars;
3685  vals = consdata->vals;
3686 
3687  for( v = 0; v < consdata->nvars; ++v )
3688  {
3689  assert(vars[v] != NULL);
3690  assert(!SCIPisZero(scip, vals[v]));
3691 
3692  if( SCIPisPositive(scip, vals[v]) )
3693  {
3694  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3695  }
3696  else
3697  {
3698  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3699  }
3700  }
3701  }
3702  }
3703 
3704  /* 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 */
3705  if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3706  {
3707  consdata->boundstightened = 0;
3708  consdata->presolved = FALSE;
3709  consdata->cliquesadded = FALSE;
3710  consdata->implsadded = FALSE;
3711 
3712  /* mark the constraint for propagation */
3713  if( SCIPconsIsTransformed(cons) )
3714  {
3715  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3716  }
3717  }
3718 
3719  /* set new right hand side and update constraint data */
3720  consdata->rhs = rhs;
3721  consdata->changed = TRUE;
3722  consdata->normalized = FALSE;
3723  consdata->upgradetried = FALSE;
3724  consdata->rangedrowpropagated = 0;
3725 
3726  /* update the rhs of the LP row */
3727  if( consdata->row != NULL )
3728  {
3729  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3730  }
3731 
3732  return SCIP_OKAY;
3733 }
3734 
3735 /** adds coefficient in linear constraint */
3736 static
3738  SCIP* scip, /**< SCIP data structure */
3739  SCIP_CONS* cons, /**< linear constraint */
3740  SCIP_VAR* var, /**< variable of constraint entry */
3741  SCIP_Real val /**< coefficient of constraint entry */
3742  )
3743 {
3744  SCIP_CONSDATA* consdata;
3745  SCIP_Bool transformed;
3746 
3747  assert(scip != NULL);
3748  assert(cons != NULL);
3749  assert(var != NULL);
3750 
3751  /* relaxation-only variables must not be used in checked or enforced constraints */
3752  assert(!SCIPvarIsRelaxationOnly(var) || (!SCIPconsIsChecked(cons) && !SCIPconsIsEnforced(cons)));
3753 
3754  /* ignore coefficient if it is nearly zero */
3755  if( SCIPisZero(scip, val) )
3756  return SCIP_OKAY;
3757 
3758  consdata = SCIPconsGetData(cons);
3759  assert(consdata != NULL);
3760 
3761  /* are we in the transformed problem? */
3762  transformed = SCIPconsIsTransformed(cons);
3763 
3764  /* always use transformed variables in transformed constraints */
3765  if( transformed )
3766  {
3767  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3768  }
3769  assert(var != NULL);
3770  assert(transformed == SCIPvarIsTransformed(var));
3771 
3772  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3773  consdata->vars[consdata->nvars] = var;
3774  consdata->vals[consdata->nvars] = val;
3775  consdata->nvars++;
3776 
3777  /* capture variable */
3778  SCIP_CALL( SCIPcaptureVar(scip, var) );
3779 
3780  /* if we are in transformed problem, the variable needs an additional event data */
3781  if( transformed )
3782  {
3783  if( consdata->eventdata != NULL )
3784  {
3785  SCIP_CONSHDLR* conshdlr;
3786  SCIP_CONSHDLRDATA* conshdlrdata;
3787 
3788  /* check for event handler */
3789  conshdlr = SCIPconsGetHdlr(cons);
3790  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3791  assert(conshdlrdata != NULL);
3792  assert(conshdlrdata->eventhdlr != NULL);
3793 
3794  /* initialize eventdata array */
3795  consdata->eventdata[consdata->nvars-1] = NULL;
3796 
3797  /* catch bound change events of variable */
3798  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3799  }
3800 
3801  /* update minimum and maximum activities */
3802  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3803 
3804  /* update maximum activity delta */
3805  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3806  {
3807  SCIP_Real lb;
3808  SCIP_Real ub;
3809 
3810  lb = SCIPvarGetLbLocal(var);
3811  ub = SCIPvarGetUbLocal(var);
3812 
3813  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3814  {
3815  consdata->maxactdelta = SCIPinfinity(scip);
3816  consdata->maxactdeltavar = var;
3817  }
3818  else
3819  {
3820  SCIP_Real domain = ub - lb;
3821  SCIP_Real delta = REALABS(val) * domain;
3822 
3823  if( delta > consdata->maxactdelta )
3824  {
3825  consdata->maxactdelta = delta;
3826  consdata->maxactdeltavar = var;
3827  }
3828  }
3829  }
3830  }
3831 
3832  /* install rounding locks for new variable */
3833  SCIP_CALL( lockRounding(scip, cons, var, val) );
3834 
3835  /* mark the constraint for propagation */
3836  if( transformed )
3837  {
3838  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3839  }
3840 
3841  consdata->boundstightened = 0;
3842  consdata->presolved = FALSE;
3843  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3844 
3845  if( consdata->validsignature )
3846  consdataUpdateSignatures(consdata, consdata->nvars-1);
3847 
3848  consdata->changed = TRUE;
3849  consdata->normalized = FALSE;
3850  consdata->upgradetried = FALSE;
3851  consdata->cliquesadded = FALSE;
3852  consdata->implsadded = FALSE;
3853  consdata->rangedrowpropagated = 0;
3854 
3855  if( consdata->nvars == 1 )
3856  {
3857  consdata->indexsorted = TRUE;
3858  consdata->coefsorted = TRUE;
3859  consdata->merged = TRUE;
3860  }
3861  else
3862  {
3863  consdata->merged = FALSE;
3864 
3865  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
3866  {
3867  consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3868  consdata->coefsorted = FALSE;
3869  }
3870  else
3871  {
3872  consdata->indexsorted = FALSE;
3873  consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3874  }
3875  }
3876 
3877  /* update hascontvar and hasnonbinvar flags */
3878  if( consdata->hasnonbinvalid && !consdata->hascontvar )
3879  {
3880  SCIP_VARTYPE vartype = SCIPvarGetType(var);
3881 
3882  if( vartype != SCIP_VARTYPE_BINARY )
3883  {
3884  consdata->hasnonbinvar = TRUE;
3885 
3886  if( vartype == SCIP_VARTYPE_CONTINUOUS )
3887  consdata->hascontvar = TRUE;
3888  }
3889  }
3890 
3891  /* add the new coefficient to the LP row */
3892  if( consdata->row != NULL )
3893  {
3894  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3895  }
3896 
3897  return SCIP_OKAY;
3898 }
3899 
3900 /** deletes coefficient at given position from linear constraint data */
3901 static
3903  SCIP* scip, /**< SCIP data structure */
3904  SCIP_CONS* cons, /**< linear constraint */
3905  int pos /**< position of coefficient to delete */
3906  )
3907 {
3908  SCIP_CONSDATA* consdata;
3909  SCIP_VAR* var;
3910  SCIP_Real val;
3911 
3912  assert(scip != NULL);
3913  assert(cons != NULL);
3914 
3915  consdata = SCIPconsGetData(cons);
3916  assert(consdata != NULL);
3917  assert(0 <= pos && pos < consdata->nvars);
3918 
3919  var = consdata->vars[pos];
3920  val = consdata->vals[pos];
3921  assert(var != NULL);
3922 
3923  /* remove rounding locks for deleted variable */
3924  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3925 
3926  /* if we are in transformed problem, delete the event data of the variable */
3927  if( SCIPconsIsTransformed(cons) )
3928  {
3929  SCIP_CONSHDLR* conshdlr;
3930  SCIP_CONSHDLRDATA* conshdlrdata;
3931 
3932  /* check for event handler */
3933  conshdlr = SCIPconsGetHdlr(cons);
3934  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3935  assert(conshdlrdata != NULL);
3936  assert(conshdlrdata->eventhdlr != NULL);
3937 
3938  /* drop bound change events of variable */
3939  if( consdata->eventdata != NULL )
3940  {
3941  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3942  assert(consdata->eventdata[pos] == NULL);
3943  }
3944  }
3945 
3946  /* move the last variable to the free slot */
3947  if( pos != consdata->nvars - 1 )
3948  {
3949  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3950  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3951 
3952  if( consdata->eventdata != NULL )
3953  {
3954  consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3955  assert(consdata->eventdata[pos] != NULL);
3956  consdata->eventdata[pos]->varpos = pos;
3957  }
3958 
3959  consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3960  consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3961  }
3962  consdata->nvars--;
3963 
3964  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3965  * of the remaining variable, or give exactly 0.0)
3966  */
3967  if( consdata->nvars <= 1 )
3968  consdataInvalidateActivities(consdata);
3969  else
3970  {
3971  if( SCIPconsIsTransformed(cons) )
3972  {
3973  /* if we are in transformed problem, update minimum and maximum activities */
3974  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3975 
3976  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3977  * delta needs to be recalculated on the next real propagation
3978  */
3979  if( consdata->maxactdeltavar == var )
3980  {
3981  consdata->maxactdelta = SCIP_INVALID;
3982  consdata->maxactdeltavar = NULL;
3983  }
3984  }
3985  }
3986 
3987  /* mark the constraint for propagation */
3988  if( SCIPconsIsTransformed(cons) )
3989  {
3990  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3991  }
3992 
3993  consdata->boundstightened = 0;
3994  consdata->presolved = FALSE;
3995  consdata->validsignature = FALSE;
3996  consdata->changed = TRUE;
3997  consdata->normalized = FALSE;
3998  consdata->upgradetried = FALSE;
3999  consdata->cliquesadded = FALSE;
4000  consdata->implsadded = FALSE;
4001  consdata->rangedrowpropagated = 0;
4002 
4003  /* check if hasnonbinvar flag might be incorrect now */
4004  if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
4005  {
4006  consdata->hasnonbinvalid = FALSE;
4007  }
4008 
4009  /* delete coefficient from the LP row */
4010  if( consdata->row != NULL )
4011  {
4012  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
4013  }
4014 
4015  /* release variable */
4016  SCIP_CALL( SCIPreleaseVar(scip, &var) );
4017 
4018  return SCIP_OKAY;
4019 }
4020 
4021 /** changes coefficient value at given position of linear constraint data */
4022 static
4024  SCIP* scip, /**< SCIP data structure */
4025  SCIP_CONS* cons, /**< linear constraint */
4026  int pos, /**< position of coefficient to delete */
4027  SCIP_Real newval /**< new value of coefficient */
4028  )
4029 {
4030  SCIP_CONSDATA* consdata;
4031  SCIP_VAR* var;
4032  SCIP_Real val;
4033  SCIP_Bool locked;
4034  int i;
4035 
4036  assert(scip != NULL);
4037  assert(cons != NULL);
4038  assert(!SCIPisZero(scip, newval));
4039 
4040  consdata = SCIPconsGetData(cons);
4041  assert(consdata != NULL);
4042  assert(0 <= pos && pos < consdata->nvars);
4043  assert(!SCIPisZero(scip, newval));
4044 
4045  var = consdata->vars[pos];
4046  val = consdata->vals[pos];
4047  assert(var != NULL);
4048  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
4049 
4050  locked = FALSE;
4051  for( i = 0; i < NLOCKTYPES && !locked; i++ )
4052  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
4053 
4054  /* if necessary, update the rounding locks of the variable */
4055  if( locked && newval * val < 0.0 )
4056  {
4057  assert(SCIPconsIsTransformed(cons));
4058 
4059  /* remove rounding locks for variable with old coefficient */
4060  SCIP_CALL( unlockRounding(scip, cons, var, val) );
4061 
4062  /* install rounding locks for variable with new coefficient */
4063  SCIP_CALL( lockRounding(scip, cons, var, newval) );
4064  }
4065 
4066  /* change the value */
4067  consdata->vals[pos] = newval;
4068 
4069  if( consdata->coefsorted )
4070  {
4071  if( pos > 0 )
4072  consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
4073  if( consdata->coefsorted && pos < consdata->nvars - 1 )
4074  consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
4075  }
4076 
4077  /* update minimum and maximum activities */
4078  if( SCIPconsIsTransformed(cons) )
4079  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
4080 
4081  /* mark the constraint for propagation */
4082  if( SCIPconsIsTransformed(cons) )
4083  {
4084  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
4085  }
4086 
4087  consdata->boundstightened = 0;
4088  consdata->presolved = FALSE;
4089  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
4090  consdata->changed = TRUE;
4091  consdata->normalized = FALSE;
4092  consdata->upgradetried = FALSE;
4093  consdata->cliquesadded = FALSE;
4094  consdata->implsadded = FALSE;
4095  consdata->rangedrowpropagated = 0;
4096 
4097  return SCIP_OKAY;
4098 }
4099 
4100 /** scales a linear constraint with a constant scalar */
4101 static
4103  SCIP* scip, /**< SCIP data structure */
4104  SCIP_CONS* cons, /**< linear constraint to scale */
4105  SCIP_Real scalar /**< value to scale constraint with */
4106  )
4107 {
4108  SCIP_CONSDATA* consdata;
4109  SCIP_Real newval;
4110  SCIP_Real absscalar;
4111  int i;
4112 
4113  assert(scip != NULL);
4114  assert(cons != NULL);
4115 
4116  consdata = SCIPconsGetData(cons);
4117  assert(consdata != NULL);
4118  assert(consdata->row == NULL);
4119  assert(!SCIPisEQ(scip, scalar, 1.0));
4120 
4121  if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4122  || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4123  {
4124  SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4125  SCIPconsGetName(cons), scalar);
4126 
4127  return SCIP_OKAY;
4128  }
4129 
4130  /* scale the coefficients */
4131  for( i = consdata->nvars - 1; i >= 0; --i )
4132  {
4133  newval = scalar * consdata->vals[i];
4134 
4135  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4136  * flooring down our new value
4137  */
4138  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4139  newval = SCIPfeasFloor(scip, newval + 0.5);
4140 
4141  if( SCIPisZero(scip, newval) )
4142  {
4143  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4144  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4145  SCIP_CALL( delCoefPos(scip, cons, i) );
4146  }
4147  else
4148  consdata->vals[i] = newval;
4149  }
4150 
4151  /* scale the sides */
4152  if( scalar < 0.0 )
4153  {
4154  SCIP_Real lhs;
4155 
4156  lhs = consdata->lhs;
4157  consdata->lhs = -consdata->rhs;
4158  consdata->rhs = -lhs;
4159  }
4160  absscalar = REALABS(scalar);
4161  if( !SCIPisInfinity(scip, -consdata->lhs) )
4162  {
4163  newval = absscalar * consdata->lhs;
4164 
4165  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4166  * flooring down our new value
4167  */
4168  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4169  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4170  else
4171  consdata->lhs = newval;
4172  }
4173  if( !SCIPisInfinity(scip, consdata->rhs) )
4174  {
4175  newval = absscalar * consdata->rhs;
4176 
4177  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4178  * our new value
4179  */
4180  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4181  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4182  else
4183  consdata->rhs = newval;
4184  }
4185 
4186  consdataInvalidateActivities(consdata);
4187  consdata->cliquesadded = FALSE;
4188  consdata->implsadded = FALSE;
4189 
4190  return SCIP_OKAY;
4191 }
4192 
4193 /** perform deletion of variables in all constraints of the constraint handler */
4194 static
4196  SCIP* scip, /**< SCIP data structure */
4197  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4198  SCIP_CONS** conss, /**< array of constraints */
4199  int nconss /**< number of constraints */
4200  )
4201 {
4202  SCIP_CONSDATA* consdata;
4203  int i;
4204  int v;
4205 
4206  assert(scip != NULL);
4207  assert(conshdlr != NULL);
4208  assert(conss != NULL);
4209  assert(nconss >= 0);
4210  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4211 
4212  /* iterate over all constraints */
4213  for( i = 0; i < nconss; i++ )
4214  {
4215  consdata = SCIPconsGetData(conss[i]);
4216 
4217  /* constraint is marked, that some of its variables were deleted */
4218  if( consdata->varsdeleted )
4219  {
4220  /* iterate over all variables of the constraint and delete them from the constraint */
4221  for( v = consdata->nvars - 1; v >= 0; --v )
4222  {
4223  if( SCIPvarIsDeleted(consdata->vars[v]) )
4224  {
4225  SCIP_CALL( delCoefPos(scip, conss[i], v) );
4226  }
4227  }
4228  consdata->varsdeleted = FALSE;
4229  }
4230  }
4231 
4232  return SCIP_OKAY;
4233 }
4234 
4235 
4236 /** normalizes a linear constraint with the following rules:
4237  * - if all coefficients have them same absolute value, change them to (-)1.0
4238  * - multiplication with +1 or -1:
4239  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4240  * if the current rule doesn't determine the sign):
4241  * 1. the right hand side must not be negative
4242  * 2. the right hand side must not be infinite
4243  * 3. the absolute value of the right hand side must be greater than that of the left hand side
4244  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4245  * 5. multiply with +1
4246  * - rationals to integrals
4247  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4248  * by the smallest common multiple of all denominators to get integral coefficients.
4249  * Forbid large denominators due to numerical stability.
4250  * - division by greatest common divisor
4251  * If all coefficients are integral, divide them by the greatest common divisor.
4252  */
4253 static
4255  SCIP* scip, /**< SCIP data structure */
4256  SCIP_CONS* cons, /**< linear constraint to normalize */
4257  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4258  )
4259 {
4260  SCIP_CONSDATA* consdata;
4261  SCIP_Real* vals;
4262  SCIP_Longint scm;
4263  SCIP_Longint nominator;
4264  SCIP_Longint denominator;
4265  SCIP_Longint gcd;
4266  SCIP_Longint maxmult;
4267  SCIP_Real epsilon;
4268  SCIP_Real feastol;
4269  SCIP_Real maxabsval;
4270  SCIP_Real minabsval;
4271  SCIP_Bool success;
4272  SCIP_Bool onlyintegral;
4273  int nvars;
4274  int mult;
4275  int nposcoeffs;
4276  int nnegcoeffs;
4277  int i;
4278 
4279  assert(scip != NULL);
4280  assert(cons != NULL);
4281  assert(infeasible != NULL);
4282 
4283  *infeasible = FALSE;
4284 
4285  /* we must not change a modifiable constraint in any way */
4286  if( SCIPconsIsModifiable(cons) )
4287  return SCIP_OKAY;
4288 
4289  /* get constraint data */
4290  consdata = SCIPconsGetData(cons);
4291  assert(consdata != NULL);
4292 
4293  /* check, if the constraint is already normalized */
4294  if( consdata->normalized )
4295  return SCIP_OKAY;
4296 
4297  /* get coefficient arrays */
4298  vals = consdata->vals;
4299  nvars = consdata->nvars;
4300  assert(nvars == 0 || vals != NULL);
4301 
4302  if( nvars == 0 )
4303  {
4304  consdata->normalized = TRUE;
4305  return SCIP_OKAY;
4306  }
4307 
4308  assert(vals != NULL);
4309 
4310  /* get maximum and minimum absolute coefficient */
4311  maxabsval = consdataGetMaxAbsval(consdata);
4312  minabsval = consdataGetMinAbsval(consdata);
4313 
4314  /* return if scaling by maxval will eliminate coefficients */
4315  if( SCIPisZero(scip, minabsval/maxabsval) )
4316  return SCIP_OKAY;
4317 
4318  /* check if the maximum absolute coefficient is not near 1.0 */
4319  if( !SCIPisEQ(scip, maxabsval, 1.0) )
4320  {
4321  SCIP_Real scalar;
4322 
4323  /* calculate scale of the average minimum and maximum absolute coefficient to 1.0 */
4324  scalar = 2.0 / (minabsval + maxabsval);
4325 
4326  /* check if all scaled absolute coefficients are near 1.0 */
4327  if( SCIPisEQ(scip, scalar * maxabsval, 1.0) )
4328  {
4329  SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4330  SCIPdebugPrintCons(scip, cons, NULL);
4331  SCIP_CALL( scaleCons(scip, cons, scalar) );
4332 
4333  /* get new consdata information, because scaleCons() might have deleted variables */
4334  vals = consdata->vals;
4335  nvars = consdata->nvars;
4336 
4337  assert(nvars == 0 || vals != NULL);
4338  }
4339  }
4340 
4341  /* nvars might have changed */
4342  if( nvars == 0 )
4343  {
4344  consdata->normalized = TRUE;
4345  return SCIP_OKAY;
4346  }
4347 
4348  assert(vals != NULL);
4349 
4350  /* calculate the maximal multiplier for common divisor calculation:
4351  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4352  * which means, a value of feastol/epsilon should be used as maximal multiplier;
4353  * additionally, we don't want to scale the constraint if this would lead to too
4354  * large coefficients
4355  */
4356  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4357  feastol = SCIPfeastol(scip);
4358  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4359 
4360  if( !consdata->hasnonbinvalid )
4361  consdataCheckNonbinvar(consdata);
4362 
4363  /* get maximum absolute coefficient */
4364  maxabsval = consdataGetMaxAbsval(consdata);
4365 
4366  /* if all variables are of integral type we will allow a greater multiplier */
4367  if( !consdata->hascontvar )
4368  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4369  else
4370  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4371 
4372  /*
4373  * multiplication with +1 or -1
4374  */
4375  mult = 0;
4376 
4377  /* 1. the right hand side must not be negative */
4378  if( SCIPisPositive(scip, consdata->lhs) )
4379  mult = +1;
4380  else if( SCIPisNegative(scip, consdata->rhs) )
4381  mult = -1;
4382 
4383  if( mult == 0 )
4384  {
4385  /* 2. the right hand side must not be infinite */
4386  if( SCIPisInfinity(scip, -consdata->lhs) )
4387  mult = +1;
4388  else if( SCIPisInfinity(scip, consdata->rhs) )
4389  mult = -1;
4390  }
4391 
4392  if( mult == 0 )
4393  {
4394  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4395  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4396  mult = +1;
4397  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4398  mult = -1;
4399  }
4400 
4401  if( mult == 0 )
4402  {
4403  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4404  nposcoeffs = 0;
4405  nnegcoeffs = 0;
4406  for( i = 0; i < nvars; ++i )
4407  {
4408  if( vals[i] > 0.0 )
4409  nposcoeffs++;
4410  else
4411  nnegcoeffs++;
4412  }
4413  if( nposcoeffs > nnegcoeffs )
4414  mult = +1;
4415  else if( nposcoeffs < nnegcoeffs )
4416  mult = -1;
4417  }
4418 
4419  if( mult == 0 )
4420  {
4421  /* 5. multiply with +1 */
4422  mult = +1;
4423  }
4424 
4425  assert(mult == +1 || mult == -1);
4426  if( mult == -1 )
4427  {
4428  /* scale the constraint with -1 */
4429  SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4430  SCIPdebugPrintCons(scip, cons, NULL);
4431  SCIP_CALL( scaleCons(scip, cons, -1.0) );
4432 
4433  /* scalecons() can delete variables, but scaling with -1 should not do that */
4434  assert(nvars == consdata->nvars);
4435  }
4436 
4437  /*
4438  * rationals to integrals
4439  *
4440  * @todo try scaling only on behalf of non-continuous variables
4441  */
4442  success = TRUE;
4443  scm = 1;
4444  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4445  {
4446  if( !SCIPisIntegral(scip, vals[i]) )
4447  {
4448  /* epsilon has been slightly decreased above - to be on the safe side */
4449  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4450  if( success )
4451  scm = SCIPcalcSmaComMul(scm, denominator);
4452  }
4453  }
4454  assert(scm >= 1);
4455 
4456  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4457  * their greatest common divisor
4458  */
4459  onlyintegral = TRUE;
4460  if( scm == 1 )
4461  {
4462  for( i = nvars - 1; i >= 0; --i )
4463  {
4464  if( !SCIPisIntegral(scip, vals[i]) )
4465  {
4466  onlyintegral = FALSE;
4467  break;
4468  }
4469  }
4470  }
4471 
4472  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4473  if( success && scm != 1 )
4474  {
4475  /* scale the constraint with the smallest common multiple of all denominators */
4476  SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4477  SCIPdebugPrintCons(scip, cons, NULL);
4478  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4479 
4480  if( consdata->validmaxabsval )
4481  {
4482  consdata->maxabsval *= REALABS((SCIP_Real)scm);
4483  if( !SCIPisIntegral(scip, consdata->maxabsval) )
4484  {
4485  consdata->validmaxabsval = FALSE;
4486  consdata->maxabsval = SCIP_INVALID;
4487  consdataCalcMaxAbsval(consdata);
4488  }
4489  }
4490 
4491  if( consdata->validminabsval )
4492  {
4493  consdata->minabsval *= REALABS((SCIP_Real)scm);
4494  if( !SCIPisIntegral(scip, consdata->minabsval) )
4495  {
4496  consdata->validminabsval = FALSE;
4497  consdata->minabsval = SCIP_INVALID;
4498  consdataCalcMinAbsval(consdata);
4499  }
4500  }
4501 
4502  /* get new consdata information, because scalecons() might have deleted variables */
4503  vals = consdata->vals;
4504  nvars = consdata->nvars;
4505  assert(nvars == 0 || vals != NULL);
4506  }
4507 
4508  /*
4509  * division by greatest common divisor
4510  */
4511  if( success && nvars >= 1 )
4512  {
4513  /* all coefficients are integral: divide them by their greatest common divisor */
4514  assert(SCIPisIntegral(scip, vals[0]));
4515 
4516  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4517  for( i = 1; i < nvars && gcd > 1; ++i )
4518  {
4519  assert(SCIPisIntegral(scip, vals[i]));
4520  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4521  }
4522 
4523  if( gcd > 1 )
4524  {
4525  /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4526  if( !consdata->hascontvar && onlyintegral )
4527  {
4528  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4529  {
4530  *infeasible = TRUE;
4531 
4532  SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4533  SCIPdebugPrintCons(scip, cons, NULL);
4534 
4535  return SCIP_OKAY;
4536  }
4537  }
4538 
4539  /* divide the constraint by the greatest common divisor of the coefficients */
4540  SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4541  SCIPdebugPrintCons(scip, cons, NULL);
4542  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4543 
4544  if( consdata->validmaxabsval )
4545  {
4546  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4547  }
4548  if( consdata->validminabsval )
4549  {
4550  consdata->minabsval /= REALABS((SCIP_Real)gcd);
4551  }
4552  }
4553  }
4554 
4555  /* mark constraint to be normalized */
4556  consdata->normalized = TRUE;
4557 
4558  SCIPdebugMsg(scip, "normalized constraint:\n");
4559  SCIPdebugPrintCons(scip, cons, NULL);
4560 
4561  return SCIP_OKAY;
4562 }
4563 
4564 /** replaces multiple occurrences of a variable by a single coefficient */
4565 static
4567  SCIP* scip, /**< SCIP data structure */
4568  SCIP_CONS* cons /**< linear constraint */
4569  )
4570 {
4571  SCIP_CONSDATA* consdata;
4572  SCIP_VAR* var;
4573  SCIP_Real valsum;
4574  int v;
4575 
4576  assert(scip != NULL);
4577  assert(cons != NULL);
4578 
4579  consdata = SCIPconsGetData(cons);
4580  assert(consdata != NULL);
4581 
4582  if( consdata->merged )
4583  return SCIP_OKAY;
4584 
4585  /* sort the constraint */
4586  SCIP_CALL( consdataSort(scip, consdata) );
4587 
4588  /* go backwards through the constraint looking for multiple occurrences of the same variable;
4589  * backward direction is necessary, since delCoefPos() modifies the given position and
4590  * the subsequent ones
4591  */
4592  v = consdata->nvars-1;
4593  while( v >= 1 )
4594  {
4595  var = consdata->vars[v];
4596  if( consdata->vars[v-1] == var )
4597  {
4598  valsum = consdata->vals[v];
4599  do
4600  {
4601  SCIP_CALL( delCoefPos(scip, cons, v) );
4602  --v;
4603  valsum += consdata->vals[v];
4604  }
4605  while( v >= 1 && consdata->vars[v-1] == var );
4606 
4607  /* modify the last existing occurrence of the variable */
4608  assert(consdata->vars[v] == var);
4609  if( SCIPisZero(scip, valsum) )
4610  {
4611  SCIP_CALL( delCoefPos(scip, cons, v) );
4612 
4613  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4614  * delta needs to be recalculated on the next real propagation
4615  */
4616  if( consdata->maxactdeltavar == var )
4617  {
4618  consdata->maxactdelta = SCIP_INVALID;
4619  consdata->maxactdeltavar = NULL;
4620  }
4621  }
4622  else
4623  {
4624  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4625  }
4626  }
4627  --v;
4628  }
4629 
4630  consdata->merged = TRUE;
4631 
4632  return SCIP_OKAY;
4633 }
4634 
4635 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4636 static
4638  SCIP* scip, /**< SCIP data structure */
4639  SCIP_CONS* cons, /**< linear constraint */
4640  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4641  * information is not needed; in this case, we apply all fixings
4642  * instead of stopping after the first infeasible one */
4643  )
4644 {
4645  SCIP_CONSDATA* consdata;
4646  SCIP_VAR* var;
4647  SCIP_VAR** aggrvars;
4648  SCIP_Real val;
4649  SCIP_Real* aggrscalars;
4650  SCIP_Real fixedval;
4651  SCIP_Real aggrconst;
4652  int v;
4653  int naggrvars;
4654  int i;
4655 
4656  assert(scip != NULL);
4657  assert(cons != NULL);
4658 
4659  if( infeasible != NULL )
4660  *infeasible = FALSE;
4661 
4662  consdata = SCIPconsGetData(cons);
4663  assert(consdata != NULL);
4664 
4665  if( consdata->eventdata == NULL )
4666  {
4667  SCIP_CONSHDLR* conshdlr;
4668  SCIP_CONSHDLRDATA* conshdlrdata;
4669 
4670  conshdlr = SCIPconsGetHdlr(cons);
4671  assert(conshdlr != NULL);
4672 
4673  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4674  assert(conshdlrdata != NULL);
4675 
4676  /* catch bound change events of variables */
4677  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4678  assert(consdata->eventdata != NULL);
4679  }
4680 
4681  if( !consdata->removedfixings )
4682  {
4683  SCIP_Real lhssubtrahend;
4684  SCIP_Real rhssubtrahend;
4685 
4686  /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4687  * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4688  */
4689  assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4690 
4691  lhssubtrahend = 0.0;
4692  rhssubtrahend = 0.0;
4693 
4694  SCIPdebugMsg(scip, "applying fixings:\n");
4695  SCIPdebugPrintCons(scip, cons, NULL);
4696 
4697  v = 0;
4698  while( v < consdata->nvars )
4699  {
4700  var = consdata->vars[v];
4701  val = consdata->vals[v];
4702  assert(SCIPvarIsTransformed(var));
4703 
4704  switch( SCIPvarGetStatus(var) )
4705  {
4707  SCIPerrorMessage("original variable in transformed linear constraint\n");
4708  return SCIP_INVALIDDATA;
4709 
4710  case SCIP_VARSTATUS_LOOSE:
4711  case SCIP_VARSTATUS_COLUMN:
4712  ++v;
4713  break;
4714 
4715  case SCIP_VARSTATUS_FIXED:
4716  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4717  fixedval = SCIPvarGetLbGlobal(var);
4718  if( !SCIPisInfinity(scip, -consdata->lhs) )
4719  {
4720  if( SCIPisInfinity(scip, ABS(fixedval)) )
4721  {
4722  if( val * fixedval > 0.0 )
4723  {
4724  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4725  }
4726  else
4727  {
4728  if( infeasible != NULL )
4729  {
4730  /* if lhs gets infinity it means that the problem is infeasible */
4731  *infeasible = TRUE;
4732  return SCIP_OKAY;
4733  }
4734  else
4735  {
4736  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4737  }
4738  }
4739  }
4740  else
4741  lhssubtrahend += val * fixedval;
4742  }
4743  if( !SCIPisInfinity(scip, consdata->rhs) )
4744  {
4745  if( SCIPisInfinity(scip, ABS(fixedval)) )
4746  {
4747  if( val * fixedval > 0.0 )
4748  {
4749  if( infeasible != NULL )
4750  {
4751  /* if rhs gets -infinity it means that the problem is infeasible */
4752  *infeasible = TRUE;
4753  return SCIP_OKAY;
4754  }
4755  else
4756  {
4757  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4758  }
4759  }
4760  else
4761  {
4762  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4763  }
4764  }
4765  else
4766  rhssubtrahend += val * fixedval;
4767  }
4768  SCIP_CALL( delCoefPos(scip, cons, v) );
4769  break;
4770 
4772  {
4773  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4774  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4775  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4776 
4777  assert(activevar != NULL);
4778  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4779  assert(activevar != NULL);
4780 
4781  if( !SCIPisZero(scip, activescalar) )
4782  {
4783  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4784  }
4785 
4786  if( !SCIPisZero(scip, activeconstant) )
4787  {
4788  if( !SCIPisInfinity(scip, -consdata->lhs) )
4789  lhssubtrahend += activeconstant;
4790  if( !SCIPisInfinity(scip, consdata->rhs) )
4791  rhssubtrahend += activeconstant;
4792  }
4793 
4794  SCIP_CALL( delCoefPos(scip, cons, v) );
4795  break;
4796  }
4799  naggrvars = SCIPvarGetMultaggrNVars(var);
4800  aggrvars = SCIPvarGetMultaggrVars(var);
4801  aggrscalars = SCIPvarGetMultaggrScalars(var);
4802  for( i = 0; i < naggrvars; ++i )
4803  {
4804  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4805  }
4806  aggrconst = SCIPvarGetMultaggrConstant(var);
4807 
4808  if( !SCIPisInfinity(scip, -consdata->lhs) )
4809  lhssubtrahend += val * aggrconst;
4810  if( !SCIPisInfinity(scip, consdata->rhs) )
4811  rhssubtrahend += val * aggrconst;
4812 
4813  SCIP_CALL( delCoefPos(scip, cons, v) );
4814  break;
4815 
4817  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4818  aggrconst = SCIPvarGetNegationConstant(var);
4819 
4820  if( !SCIPisInfinity(scip, -consdata->lhs) )
4821  lhssubtrahend += val * aggrconst;
4822  if( !SCIPisInfinity(scip, consdata->rhs) )
4823  rhssubtrahend += val * aggrconst;
4824 
4825  SCIP_CALL( delCoefPos(scip, cons, v) );
4826  break;
4827 
4828  default:
4829  SCIPerrorMessage("unknown variable status\n");
4830  SCIPABORT();
4831  return SCIP_INVALIDDATA; /*lint !e527*/
4832  }
4833  }
4834 
4835  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4836  {
4837  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4838  * causing wrong fixings of other variables --> better use a real zero here;
4839  * for small numbers, polishing the difference might lead to wrong results -->
4840  * better use the exact difference in this case
4841  */
4842  if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4843  {
4844  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4845  }
4846  else
4847  {
4848  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4849  }
4850  }
4851  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
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, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4859  {
4860  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4861  }
4862  else
4863  {
4864  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4865  }
4866  }
4867  consdata->removedfixings = TRUE;
4868 
4869  SCIPdebugMsg(scip, "after fixings:\n");
4870  SCIPdebugPrintCons(scip, cons, NULL);
4871 
4872  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4873  * to clean up the constraint
4874  */
4875  SCIP_CALL( mergeMultiples(scip, cons) );
4876 
4877  SCIPdebugMsg(scip, "after merging:\n");
4878  SCIPdebugPrintCons(scip, cons, NULL);
4879  }
4880  assert(consdata->removedfixings);
4881 
4882 #ifndef NDEBUG
4883  /* check, if all fixings are applied */
4884  for( v = 0; v < consdata->nvars; ++v )
4885  assert(SCIPvarIsActive(consdata->vars[v]));
4886 #endif
4887 
4888  return SCIP_OKAY;
4889 }
4890 
4891 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4892  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4893  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4894  * conflict detecting constraint by using NULL as inferred variable
4895  */
4896 static
4898  SCIP* scip, /**< SCIP data structure */
4899  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4900  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4901  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4902  int inferpos, /**< position of the inferred variable in the vars array */
4903  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4904  )
4905 {
4906  SCIP_CONSDATA* consdata;
4907  SCIP_VAR** vars;
4908  SCIP_Real* vals;
4909  int nvars;
4910  int i;
4911 
4912  assert(scip != NULL);
4913  assert(cons != NULL);
4914 
4915  consdata = SCIPconsGetData(cons);
4917  assert(consdata != NULL);
4918 
4919  vars = consdata->vars;
4920  vals = consdata->vals;
4921  nvars = consdata->nvars;
4922 
4923  assert(vars != NULL || nvars == 0);
4924  assert(vals != NULL || nvars == 0);
4925 
4926  assert(-1 <= inferpos && inferpos < nvars);
4927  assert((infervar == NULL) == (inferpos == -1));
4928  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4929 
4930  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4931  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4932  * - if the right hand side is the reason, the minimal residual activity is responsible
4933  * - if the left hand side is the reason, the maximal residual activity is responsible
4934  */
4935 
4936  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4937  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4938  {
4939  SCIP_Real minresactivity;
4940  SCIP_Real maxresactivity;
4941  SCIP_Bool minisrelax;
4942  SCIP_Bool maxisrelax;
4943  SCIP_Bool isminsettoinfinity;
4944  SCIP_Bool ismaxsettoinfinity;
4945 
4946  minresactivity = -SCIPinfinity(scip);
4947  maxresactivity = SCIPinfinity(scip);
4948 
4949  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4950  if( infervar != NULL )
4951  {
4952  assert(vals != NULL); /* for flexelint */
4953  if( reasonisrhs )
4954  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4955  &minisrelax, NULL, &isminsettoinfinity, NULL);
4956  else
4957  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4958  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4959  }
4960  else
4961  {
4962  if( reasonisrhs )
4963  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4964  &minisrelax, NULL, &isminsettoinfinity, NULL);
4965  else
4966  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4967  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4968  }
4969 
4970  /* we can only do something clever, if the residual activity is finite and not relaxed */
4971  if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4972  {
4973  SCIP_Real rescap;
4974  SCIP_Bool resactisinf;
4975 
4976  resactisinf = FALSE;
4977 
4978  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4979  * than its inferred bound
4980  */
4981  if( infervar != NULL )
4982  {
4983  assert(vals != NULL); /* for flexelint */
4984 
4985  if( reasonisrhs )
4986  {
4987  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4988  {
4989  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4990  if( SCIPisInfinity(scip, -minresactivity) )
4991  resactisinf = TRUE;
4992  }
4993  rescap = consdata->rhs - minresactivity;
4994  }
4995  else
4996  {
4997  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4998  {
4999  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
5000  if( SCIPisInfinity(scip, maxresactivity) )
5001  resactisinf = TRUE;
5002  }
5003  rescap = consdata->lhs - maxresactivity;
5004  }
5005 
5006  if( reasonisrhs == (vals[inferpos] > 0.0) )
5007  rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
5008  else
5009  rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
5010  }
5011  else
5012  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
5013 
5014  if( !resactisinf )
5015  {
5016  /* now add bounds as reasons until the residual capacity is exceeded */
5017  for( i = 0; i < nvars; ++i )
5018  {
5019  assert( vars != NULL && vals != NULL ); /* for lint */
5020 
5021  /* zero coefficients and the inferred variable can be ignored */
5022  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5023  continue;
5024 
5025  /* check if the residual capacity is exceeded */
5026  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
5027  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
5028  break;
5029 
5030  /* update the residual capacity due to the local bound of this variable */
5031  if( reasonisrhs == (vals[i] > 0.0) )
5032  {
5033  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
5034  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5035  rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
5036  }
5037  else
5038  {
5039  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
5040  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5041  rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
5042  }
5043  }
5044  return SCIP_OKAY;
5045  }
5046  }
5047  }
5048 
5049  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
5050  for( i = 0; i < nvars; ++i )
5051  {
5052  assert(vars != NULL); /* for flexelint */
5053  assert(vals != NULL); /* for flexelint */
5054 
5055  /* zero coefficients and the inferred variable can be ignored */
5056  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5057  continue;
5058 
5059  if( reasonisrhs == (vals[i] > 0.0) )
5060  {
5061  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
5062  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5063  }
5064  else
5065  {
5066  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
5067  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5068  }
5069  }
5070 
5071  return SCIP_OKAY;
5072 }
5073 
5074 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
5075  * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
5076  * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
5077  */
5078 static
5080  SCIP* scip, /**< SCIP data structure */
5081  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5082  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
5083  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5084  int inferpos /**< position of the inferred variable in the vars array, or -1 */
5085  )
5086 {
5087  SCIP_CONSDATA* consdata;
5088  SCIP_VAR** vars;
5089  int nvars;
5090  int v;
5091 
5092  assert(scip != NULL);
5093  assert(cons != NULL);
5094 
5095  consdata = SCIPconsGetData(cons);
5096  assert(consdata != NULL);
5097  vars = consdata->vars;
5098  nvars = consdata->nvars;
5099  assert(vars != NULL || nvars == 0);
5100  assert(-1 <= inferpos && inferpos < nvars);
5101  assert((infervar == NULL) == (inferpos == -1));
5102  assert(inferpos == -1 || vars != NULL);
5103  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5104 
5105  /* collect all fixed variables */
5106  for( v = nvars - 1; v >= 0; --v )
5107  {
5108  assert(vars != NULL); /* for flexelint */
5109 
5110  /* need to add old bounds before propagation of inferrence variable */
5111  if( vars[v] == infervar )
5112  {
5113  assert(vars[v] != NULL);
5114 
5115  if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5116  {
5117  /* @todo get boundchange index before this last boundchange and correct the index */
5118  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5119  }
5120 
5121  if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5122  {
5123  /* @todo get boundchange index before this last boundchange and correct the index */
5124  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5125  }
5126 
5127  continue;
5128  }
5129 
5130  /* check for fixed variables */
5131  if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5132  {
5133  /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5134  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5135  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5136  }
5137  }
5138 
5139  return SCIP_OKAY;
5140 }
5141 
5142 /** add reasoning variables to conflict candidate queue which led to the conflict */
5143 static
5145  SCIP* scip, /**< SCIP data structure */
5146  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5147  int nvars, /**< number of variables reasoning the infeasibility */
5148  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5149  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5150  )
5151 {
5152  int v;
5153 
5154  assert(scip != NULL);
5155 
5156  /* collect all variables for which the local bounds differ from their global bounds */
5157  for( v = nvars - 1; v >= 0; --v )
5158  {
5159  assert(vars != NULL);
5160 
5161  /* check for local bound changes variables */
5162  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5163  {
5164  /* add conflict bound */
5165  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5166  }
5167 
5168  if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5169  {
5170  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5171  }
5172  }
5173 
5174  if( var != NULL )
5175  {
5176  if( bound < SCIPvarGetLbLocal(var) )
5177  {
5178  SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5179  }
5180 
5181  if( bound > SCIPvarGetUbLocal(var) )
5182  {
5183  SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5184  }
5185  }
5186 
5187  return SCIP_OKAY;
5188 }
5189 
5190 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5191  * propagation rule (see propagateCons()):
5192  * (1) activity residuals of all other variables tighten bounds of single variable
5193  */
5194 static
5196  SCIP* scip, /**< SCIP data structure */
5197  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5198  SCIP_VAR* infervar, /**< variable that was deduced */
5199  INFERINFO inferinfo, /**< inference information */
5200  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5201  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5202  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5203  )
5204 {
5205  SCIP_CONSDATA* consdata;
5206  SCIP_VAR** vars;
5207 #ifndef NDEBUG
5208  SCIP_Real* vals;
5209 #endif
5210  int nvars;
5211  int inferpos;
5212 
5213  assert(scip != NULL);
5214  assert(cons != NULL);
5215  assert(result != NULL);
5216 
5217  consdata = SCIPconsGetData(cons);
5218  assert(consdata != NULL);
5219  vars = consdata->vars;
5220  nvars = consdata->nvars;
5221 #ifndef NDEBUG
5222  vals = consdata->vals;
5223  assert(vars != NULL);
5224  assert(vals != NULL);
5225 #endif
5226 
5227  /* get the position of the inferred variable in the vars array */
5228  inferpos = inferInfoGetPos(inferinfo);
5229  if( inferpos >= nvars || vars[inferpos] != infervar )
5230  {
5231  /* find inference variable in constraint */
5232  /**@todo use a binary search here; the variables can be sorted by variable index */
5233  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5234  {}
5235  }
5236  assert(inferpos < nvars);
5237  assert(vars[inferpos] == infervar);
5238  assert(!SCIPisZero(scip, vals[inferpos]));
5239 
5240  switch( inferInfoGetProprule(inferinfo) )
5241  {
5242  case PROPRULE_1_RHS:
5243  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5244  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5245  * domain in order to not exceed the right hand side of the inequality
5246  */
5247  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5248  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5249  *result = SCIP_SUCCESS;
5250  break;
5251 
5252  case PROPRULE_1_LHS:
5253  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5254  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5255  * domain in order to not fall below the left hand side of the inequality
5256  */
5257  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5258  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5259  *result = SCIP_SUCCESS;
5260  break;
5261 
5262  case PROPRULE_1_RANGEDROW:
5263  /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5264  * the given inference variable to their bounds in this given ranged row
5265  */
5266 
5267  /* check that we really have a ranged row here */
5268  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5269  SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5270  *result = SCIP_SUCCESS;
5271  break;
5272 
5273  case PROPRULE_INVALID:
5274  default:
5275  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5276  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5277  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5278  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5279  SCIPinfoMessage(scip, NULL, ";\n");
5280  return SCIP_INVALIDDATA;
5281  }
5282 
5283  return SCIP_OKAY;
5284 }
5285 
5286 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5287 static
5289  SCIP* scip, /**< SCIP data structure */
5290  SCIP_CONS* cons, /**< conflict detecting constraint */
5291  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5292  )
5293 {
5294  /* conflict analysis can only be applied in solving stage and if it is turned on */
5296  return SCIP_OKAY;
5297 
5298  /* initialize conflict analysis */
5300 
5301  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5302  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5303 
5304  /* analyze the conflict */
5305  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5306 
5307  return SCIP_OKAY;
5308 }
5309 
5310 /** check if there is any hope of tightening some bounds */
5311 static
5313  SCIP_CONS* cons /**< linear constraint */
5314  )
5315 {
5316  SCIP_CONSDATA* consdata;
5317  int infcountmin;
5318  int infcountmax;
5319 
5320  consdata = SCIPconsGetData(cons);
5321  assert(consdata != NULL);
5322 
5323  infcountmin = consdata->minactivityneginf
5324  + consdata->minactivityposinf
5325  + consdata->minactivityneghuge
5326  + consdata->minactivityposhuge;
5327  infcountmax = consdata->maxactivityneginf
5328  + consdata->maxactivityposinf
5329  + consdata->maxactivityneghuge
5330  + consdata->maxactivityposhuge;
5332  if( infcountmin > 1 && infcountmax > 1 )
5333  return FALSE;
5334 
5335  return TRUE;
5336 }
5337 
5338 /** tighten upper bound */
5339 static
5341  SCIP* scip, /**< SCIP data structure */
5342  SCIP_CONS* cons, /**< linear constraint */
5343  int pos, /**< variable position */
5344  PROPRULE proprule, /**< propagation rule that deduced the value */
5345  SCIP_Real newub, /**< new upper bound */
5346  SCIP_Real oldub, /**< old upper bound */
5347  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5348  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5349  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5350  )
5351 {
5352  SCIP_CONSDATA* consdata;
5353  SCIP_VAR* var;
5354  SCIP_Real lb;
5355  SCIP_Bool infeasible;
5356  SCIP_Bool tightened;
5357 
5358  assert(cons != NULL);
5359  assert(!SCIPisInfinity(scip, newub));
5360 
5361  consdata = SCIPconsGetData(cons);
5362  assert(consdata != NULL);
5363  var = consdata->vars[pos];
5364  assert(var != NULL);
5365 
5366  lb = SCIPvarGetLbLocal(var);
5367  newub = SCIPadjustedVarUb(scip, var, newub);
5368 
5369  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5370  {
5371  SCIP_VARTYPE vartype;
5372 
5373  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5374  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5375  QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5376 
5377  vartype = SCIPvarGetType(var);
5378 
5379  /* tighten upper bound */
5380  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5381 
5382  if( infeasible )
5383  {
5384  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5385  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5386 
5387  /* analyze conflict */
5388  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5389 
5390  *cutoff = TRUE;
5391  }
5392  else if( tightened )
5393  {
5394  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5395  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5396  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5397 
5398  (*nchgbds)++;
5399 
5400  /* if variable type was changed we might be able to upgrade the constraint */
5401  if( vartype != SCIPvarGetType(var) )
5402  consdata->upgradetried = FALSE;
5403  }
5404  }
5405  return SCIP_OKAY;
5406 }
5407 
5408 /** tighten lower bound */
5409 static
5411  SCIP* scip, /**< SCIP data structure */
5412  SCIP_CONS* cons, /**< linear constraint */
5413  int pos, /**< variable position */
5414  PROPRULE proprule, /**< propagation rule that deduced the value */
5415  SCIP_Real newlb, /**< new lower bound */
5416  SCIP_Real oldlb, /**< old lower bound */
5417  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5418  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5419  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5420  )
5421 {
5422  SCIP_CONSDATA* consdata;
5423  SCIP_VAR* var;
5424  SCIP_Real ub;
5425  SCIP_Bool infeasible;
5426  SCIP_Bool tightened;
5427 
5428  assert(cons != NULL);
5429  assert(!SCIPisInfinity(scip, newlb));
5430 
5431  consdata = SCIPconsGetData(cons);
5432  assert(consdata != NULL);
5433  var = consdata->vars[pos];
5434  assert(var != NULL);
5435 
5436  ub = SCIPvarGetUbLocal(var);
5437  newlb = SCIPadjustedVarLb(scip, var, newlb);
5438 
5439  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5440  {
5441  SCIP_VARTYPE vartype;
5442 
5443  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5444  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5445  QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5446 
5447  vartype = SCIPvarGetType(var);
5448 
5449  /* tighten lower bound */
5450  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5451 
5452  if( infeasible )
5453  {
5454  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5455  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5456 
5457  /* analyze conflict */
5458  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5459 
5460  *cutoff = TRUE;
5461  }
5462  else if( tightened )
5463  {
5464  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5465  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5466  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5467 
5468  (*nchgbds)++;
5469 
5470  /* if variable type was changed we might be able to upgrade the constraint */
5471  if( vartype != SCIPvarGetType(var) )
5472  consdata->upgradetried = FALSE;
5473  }
5474  }
5475  return SCIP_OKAY;
5476 }
5477 
5478 /** tightens bounds of a single variable due to activity bounds (easy case) */
5479 static
5481  SCIP* scip, /**< SCIP data structure */
5482  SCIP_CONS* cons, /**< linear constraint */
5483  int pos, /**< position of the variable in the vars array */
5484  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5485  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5486  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5487  )
5488 {
5489  SCIP_CONSDATA* consdata;
5490  SCIP_VAR* var;
5491  SCIP_Real val;
5492  SCIP_Real lb;
5493  SCIP_Real ub;
5494  SCIP_Real lhs;
5495  SCIP_Real rhs;
5496 
5497  assert(scip != NULL);
5498  assert(cons != NULL);
5499  assert(cutoff != NULL);
5500  assert(nchgbds != NULL);
5501 
5502  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5503  if( SCIPconsIsModifiable(cons) )
5504  return SCIP_OKAY;
5505 
5506  consdata = SCIPconsGetData(cons);
5507  assert(consdata != NULL);
5508  assert(0 <= pos && pos < consdata->nvars);
5509 
5510  *cutoff = FALSE;
5511 
5512  var = consdata->vars[pos];
5513  assert(var != NULL);
5514 
5515  /* we cannot tighten bounds of multi-aggregated variables */
5517  return SCIP_OKAY;
5518 
5519  val = consdata->vals[pos];
5520  lhs = consdata->lhs;
5521  rhs = consdata->rhs;
5522  assert(!SCIPisZero(scip, val));
5523  assert(!SCIPisInfinity(scip, lhs));
5524  assert(!SCIPisInfinity(scip, -rhs));
5525 
5526  lb = SCIPvarGetLbLocal(var);
5527  ub = SCIPvarGetUbLocal(var);
5528  assert(SCIPisLE(scip, lb, ub));
5529 
5530  /* recompute activities if needed */
5531  if( !consdata->validactivities )
5532  consdataCalcActivities(scip, consdata);
5533  assert(consdata->validactivities);
5534  if( !consdata->validminact )
5535  consdataRecomputeMinactivity(scip, consdata);
5536  assert(consdata->validminact);
5537 
5538  if( val > 0.0 )
5539  {
5540  /* check, if we can tighten the variable's upper bound */
5541  if( !SCIPisInfinity(scip, rhs) )
5542  {
5543  SCIP_Real slack;
5544  SCIP_Real alpha;
5545 
5546  /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5547  assert(consdata->validminact);
5548 
5549  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5550  if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5551  {
5552  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5553  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5554 
5555  *cutoff = TRUE;
5556  return SCIP_OKAY;
5557  }
5558 
5559  slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5560 
5561  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5562  * it to zero
5563  */
5564  if( !SCIPisPositive(scip, slack) )
5565  slack = 0.0;
5566 
5567  alpha = val * (ub - lb);
5568  assert(!SCIPisNegative(scip, alpha));
5569 
5570  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5571  {
5572  SCIP_Real newub;
5573 
5574  /* compute new upper bound */
5575  newub = lb + (slack / val);
5576 
5577  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5578 
5579  if( *cutoff )
5580  {
5581  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5582  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5583 
5584  return SCIP_OKAY;
5585  }
5586 
5587  /* collect the new upper bound which is needed for the lower bound computation */
5588  ub = SCIPvarGetUbLocal(var);
5589  }
5590  }
5591 
5592  /* check, if we can tighten the variable's lower bound */
5593  if( !SCIPisInfinity(scip, -lhs) )
5594  {
5595  SCIP_Real slack;
5596  SCIP_Real alpha;
5597 
5598  /* make sure the max activity is reliable */
5599  if( !consdata->validmaxact )
5600  {
5601  consdataRecomputeMaxactivity(scip, consdata);
5602  }
5603  assert(consdata->validmaxact);
5604 
5605  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5606  if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5607  {
5608  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5609  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5610 
5611  *cutoff = TRUE;
5612  return SCIP_OKAY;
5613  }
5614 
5615  slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5616 
5617  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5618  * it to zero
5619  */
5620  if( !SCIPisPositive(scip, slack) )
5621  slack = 0.0;
5622 
5623  alpha = val * (ub - lb);
5624  assert(!SCIPisNegative(scip, alpha));
5625 
5626  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5627  {
5628  SCIP_Real newlb;
5629 
5630  /* compute new lower bound */
5631  newlb = ub - (slack / val);
5632 
5633  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5634 
5635  if( *cutoff )
5636  {
5637  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5638  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5639 
5640  return SCIP_OKAY;
5641  }
5642  }
5643  }
5644  }
5645  else
5646  {
5647  /* check, if we can tighten the variable's lower bound */
5648  if( !SCIPisInfinity(scip, rhs) )
5649  {
5650  SCIP_Real slack;
5651  SCIP_Real alpha;
5652 
5653  /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5654  assert(consdata->validminact);
5655 
5656  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5657  if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5658  {
5659  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5660  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5661 
5662  *cutoff = TRUE;
5663  return SCIP_OKAY;
5664  }
5665 
5666  slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5667 
5668  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5669  * it to zero
5670  */
5671  if( !SCIPisPositive(scip, slack) )
5672  slack = 0.0;
5673 
5674  alpha = val * (lb - ub);
5675  assert(!SCIPisNegative(scip, alpha));
5676 
5677  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5678  {
5679  SCIP_Real newlb;
5680 
5681  /* compute new lower bound */
5682  newlb = ub + slack / val;
5683 
5684  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5685 
5686  if( *cutoff )
5687  {
5688  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5689  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5690 
5691  return SCIP_OKAY;
5692  }
5693  /* collect the new lower bound which is needed for the upper bound computation */
5694  lb = SCIPvarGetLbLocal(var);
5695  }
5696  }
5697 
5698  /* check, if we can tighten the variable's upper bound */
5699  if( !SCIPisInfinity(scip, -lhs) )
5700  {
5701  SCIP_Real slack;
5702  SCIP_Real alpha;
5703 
5704  /* make sure the max activity is reliable */
5705  if( !consdata->validmaxact )
5706  {
5707  consdataRecomputeMaxactivity(scip, consdata);
5708  }
5709  assert(consdata->validmaxact);
5710 
5711  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5712  if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5713  {
5714  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5715  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5716 
5717  *cutoff = TRUE;
5718  return SCIP_OKAY;
5719  }
5720 
5721  slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5722 
5723  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5724  * it to zero
5725  */
5726  if( !SCIPisPositive(scip, slack) )
5727  slack = 0.0;
5728 
5729  alpha = val * (lb - ub);
5730  assert(!SCIPisNegative(scip, alpha));
5731 
5732  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5733  {
5734  SCIP_Real newub;
5735 
5736  /* compute new upper bound */
5737  newub = lb - (slack / val);
5738 
5739  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5740 
5741  if( *cutoff )
5742  {
5743  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5744  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5745 
5746  return SCIP_OKAY;
5747  }
5748  }
5749  }
5750  }
5751 
5752  return SCIP_OKAY;
5753 }
5754 
5755 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5756 static
5758  SCIP* scip, /**< SCIP data structure */
5759  SCIP_CONS* cons, /**< conflict detecting constraint */
5760  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5761  int nvars, /**< number of variables reasoning the infeasibility */
5762  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5763  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5764  )
5765 {
5766 #ifndef NDEBUG
5767  SCIP_CONSDATA* consdata;
5768 
5769  assert(scip != NULL);
5770  assert(cons != NULL);
5771 
5772  consdata = SCIPconsGetData(cons);
5773  assert(consdata != NULL);
5774  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5775 #endif
5777  /* conflict analysis can only be applied in solving stage and if it is turned on */
5779  return SCIP_OKAY;
5780 
5781  /* initialize conflict analysis */
5783 
5784  /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5785  SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) );
5786 
5787  /* add reasoning variables to conflict candidate queue which led to the conflict */
5788  SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5789 
5790  /* analyze the conflict */
5791  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5792 
5793  return SCIP_OKAY;
5794 }
5795 
5796 /** propagate ranged rows
5797  *
5798  * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5799  * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5800  * variables better.
5801  *
5802  * Example:
5803  * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5804  *
5805  * x3 needs to be a multiple of 3, so the instance is infeasible.
5806  *
5807  * Example:
5808  * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5809  *
5810  * The only possible value for x3 is 2, so the variable will be fixed.
5811  *
5812  * @todo add holes if possible
5813  */
5814 static
5816  SCIP* scip, /**< SCIP data structure */
5817  SCIP_CONS* cons, /**< linear constraint */
5818  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5819  int* nfixedvars, /**< pointer to count number of fixed variables */
5820  int* nchgbds, /**< pointer to count the number of bound changes */
5821  int* naddconss /**< pointer to count number of added constraints */
5822  )
5823 {
5824  SCIP_CONSHDLRDATA* conshdlrdata;
5825  SCIP_CONSHDLR* conshdlr;
5826  SCIP_CONSDATA* consdata;
5827  SCIP_VAR** infcheckvars;
5828  SCIP_Real* infcheckvals;
5829  SCIP_Real minactinfvars;
5830  SCIP_Real maxactinfvars;
5831  SCIP_Real lb;
5832  SCIP_Real ub;
5833  SCIP_Real feastol;
5834  SCIP_Real fixedact;
5835  SCIP_Real lhs;
5836  SCIP_Real rhs;
5837  SCIP_Real absminbincoef;
5838  SCIP_Longint gcd;
5839  SCIP_Longint gcdtmp;
5840  SCIP_Bool minactinfvarsinvalid;
5841  SCIP_Bool maxactinfvarsinvalid;
5842  SCIP_Bool possiblegcd;
5843  SCIP_Bool gcdisone;
5844  SCIP_Bool addartconss;
5845  int ninfcheckvars;
5846  int nunfixedvars;
5847  int nfixedconsvars;
5848  int ncontvars;
5849  int pos;
5850  int v;
5851 
5852  assert(scip != NULL);
5853  assert(cons != NULL);
5854  assert(cutoff != NULL);
5855  assert(nfixedvars != NULL);
5856  assert(nchgbds != NULL);
5857  assert(naddconss != NULL);
5858 
5859  /* modifiable constraint can be changed so we do not have all necessary information */
5860  if( SCIPconsIsModifiable(cons) )
5861  return SCIP_OKAY;
5862 
5863  consdata = SCIPconsGetData(cons);
5864  assert(consdata != NULL);
5865 
5866  /* we already did full ranged row propagation */
5867  if( consdata->rangedrowpropagated == 2 )
5868  return SCIP_OKAY;
5869 
5870  /* at least three variables are needed */
5871  if( consdata->nvars < 3 )
5872  return SCIP_OKAY;
5873 
5874  /* do nothing on normal inequalities */
5875  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5876  return SCIP_OKAY;
5877 
5878  /* get constraint handler data */
5879  conshdlr = SCIPconsGetHdlr(cons);
5880  assert(conshdlr != NULL);
5881  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5882  assert(conshdlrdata != NULL);
5883 
5884  addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5885 
5886  /* we may add artificial constraints */
5887  if( addartconss )
5888  consdata->rangedrowpropagated = 2;
5889  /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5890  * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5891  * artificial constraints
5892  */
5893  else
5894  {
5895  if( consdata->rangedrowpropagated > 0 )
5896  return SCIP_OKAY;
5897 
5898  consdata->rangedrowpropagated = 1;
5899  }
5900  fixedact = 0;
5901  nfixedconsvars = 0;
5902  /* calculate fixed activity and number of fixed variables */
5903  for( v = consdata->nvars - 1; v >= 0; --v )
5904  {
5905  /* all zero coefficients should be eliminated */
5906  assert(!SCIPisZero(scip, consdata->vals[v]));
5907 
5908  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5909  {
5910  fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5911  ++nfixedconsvars;
5912  }
5913  }
5914 
5915  /* do not work with huge fixed activities */
5916  if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5917  return SCIP_OKAY;
5918 
5919  /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5920  assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5921  lhs = consdata->lhs - fixedact;
5922  rhs = consdata->rhs - fixedact;
5923  nunfixedvars = consdata->nvars - nfixedconsvars;
5924 
5925  /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5926  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5927  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5928 
5929  absminbincoef = SCIP_REAL_MAX;
5930  ncontvars = 0;
5931  gcdisone = TRUE;
5932  possiblegcd = TRUE;
5933 
5934  /* we now partition all unfixed variables in two groups:
5935  *
5936  * the first one contains all integral variable with integral
5937  * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5938  * given
5939  *
5940  * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5941  * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5942  */
5943 
5944  /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5945  * variables
5946  */
5947  ninfcheckvars = 0;
5948  v = -1;
5949  pos = -1;
5950  do
5951  {
5952  ++v;
5953 
5954  /* partition the variables, do not change the order of collection, because it might be used later on */
5955  while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5956  !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5957  {
5958  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5959  {
5960  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5961  {
5962  ++ncontvars;
5963  }
5964  else if( SCIPvarIsBinary(consdata->vars[v]) )
5965  {
5966  SCIP_Real absval;
5967 
5968  absval = REALABS(consdata->vals[v]);
5969 
5970  if( absminbincoef > absval )
5971  absminbincoef = absval;
5972  }
5973 
5974  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5975  possiblegcd = FALSE;
5976  infcheckvars[ninfcheckvars] = consdata->vars[v];
5977  infcheckvals[ninfcheckvars] = consdata->vals[v];
5978  ++ninfcheckvars;
5979 
5980  if( pos == -1 )
5981  pos = v;
5982  }
5983  ++v;
5984  }
5985  }
5986  while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5987 
5988  /* if the first group of variables is empty, we stop */
5989  /* @todo try to propagate/split up a constraint of the form:
5990  * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5991  * 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]
5992  */
5993  if( v == consdata->nvars )
5994  goto TERMINATE;
5995 
5996  /* we need at least two non-continuous variables */
5997  if( ncontvars + 2 > nunfixedvars )
5998  goto TERMINATE;
5999 
6000  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
6001  assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
6002 
6003  feastol = SCIPfeastol(scip);
6004 
6005  gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
6006  assert(gcd >= 2);
6007 
6008  /* go on to partition the variables, do not change the order of collection, because it might be used later on;
6009  * calculate gcd over the first part of variables */
6010  for( ; v < consdata->nvars; ++v )
6011  {
6012  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6013  continue;
6014 
6015  if( SCIPvarIsBinary(consdata->vars[v]) )
6016  {
6017  SCIP_Real absval;
6018 
6019  absval = REALABS(consdata->vals[v]);
6020 
6021  if( absminbincoef > absval )
6022  absminbincoef = absval;
6023  }
6024 
6025  if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
6026  SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
6027  {
6028  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
6029  ++ncontvars;
6030 
6031  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
6032  possiblegcd = FALSE;
6033  infcheckvars[ninfcheckvars] = consdata->vars[v];
6034  infcheckvals[ninfcheckvars] = consdata->vals[v];
6035 
6036  ++ninfcheckvars;
6037 
6038  if( pos == -1 )
6039  pos = v;
6040  }
6041  else
6042  {
6043  assert(REALABS(consdata->vals[v]) > 1.5);
6044 
6045  gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
6046  assert(gcdtmp >= 1);
6047 
6048  if( gcdtmp == 1 )
6049  {
6050  infcheckvars[ninfcheckvars] = consdata->vars[v];
6051  infcheckvals[ninfcheckvars] = consdata->vals[v];
6052 
6053  ++ninfcheckvars;
6054 
6055  if( pos == -1 )
6056  pos = v;
6057  }
6058  else
6059  gcd = gcdtmp;
6060  }
6061  }
6062  assert(gcd >= 2);
6063 
6064  /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
6065  * normalizeCons() */
6066  if( ninfcheckvars == 0 )
6067  goto TERMINATE;
6068 
6069  assert(pos >= 0);
6070 
6071  minactinfvarsinvalid = FALSE;
6072  maxactinfvarsinvalid = FALSE;
6073  maxactinfvars = 0.0;
6074  minactinfvars = 0.0;
6075 
6076  /* calculate activities over all infcheckvars */
6077  for( v = ninfcheckvars - 1; v >= 0; --v )
6078  {
6079  lb = SCIPvarGetLbLocal(infcheckvars[v]);
6080  ub = SCIPvarGetUbLocal(infcheckvars[v]);
6081 
6082  if( SCIPisInfinity(scip, -lb) )
6083  {
6084  if( infcheckvals[v] < 0.0 )
6085  maxactinfvarsinvalid = TRUE;
6086  else
6087  minactinfvarsinvalid = TRUE;
6088  }
6089  else
6090  {
6091  if( infcheckvals[v] < 0.0 )
6092  maxactinfvars += infcheckvals[v] * lb;
6093  else
6094  minactinfvars += infcheckvals[v] * lb;
6095  }
6096 
6097  if( SCIPisInfinity(scip, ub) )
6098  {
6099  if( infcheckvals[v] > 0.0 )
6100  maxactinfvarsinvalid = TRUE;
6101  else
6102  minactinfvarsinvalid = TRUE;
6103  }
6104  else
6105  {
6106  if( infcheckvals[v] > 0.0 )
6107  maxactinfvars += infcheckvals[v] * ub;
6108  else
6109  minactinfvars += infcheckvals[v] * ub;
6110  }
6111 
6112  /* better abort on to big values */
6113  if( SCIPisHugeValue(scip, -minactinfvars) )
6114  minactinfvarsinvalid = TRUE;
6115  if( SCIPisHugeValue(scip, maxactinfvars) )
6116  maxactinfvarsinvalid = TRUE;
6117 
6118  if( minactinfvarsinvalid || maxactinfvarsinvalid )
6119  goto TERMINATE;
6120  }
6121  assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6122 
6123  SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6124  minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6125 
6126  /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6127  /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6128  * activities */
6129  /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6130  * !!!note!!!
6131  * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6132  * are not at their global bound
6133  */
6134 
6135  /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6136  * infeasibility */
6137  if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6138  SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6139  {
6140  SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6141  SCIPdebugPrintCons(scip, cons, NULL);
6142 
6143  /* start conflict analysis */
6144  /* @todo improve conflict analysis by adding relaxed bounds */
6145  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6146 
6147  *cutoff = TRUE;
6148  }
6149  else if( ncontvars == 0 )
6150  {
6151  SCIP_Longint gcdinfvars = -1;
6152 
6153  /* check for gcd over all infcheckvars */
6154  if( possiblegcd )
6155  {
6156  v = ninfcheckvars - 1;
6157  gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6158  assert(gcdinfvars >= 2);
6159 
6160  for( ; v >= 0 && gcdinfvars >= 2; --v )
6161  {
6162  gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6163  }
6164  }
6165  else if( gcdisone )
6166  gcdinfvars = 1;
6167 
6168  SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6169 
6170  /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6171  if( gcdinfvars >= 1 )
6172  {
6173  SCIP_Real value;
6174  SCIP_Real value2;
6175  SCIP_Real minvalue = SCIP_INVALID;
6176  SCIP_Real maxvalue = SCIP_INVALID;
6177  int nsols = 0;
6178 
6179  value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6180 
6181  /* check how many possible solutions exist */
6182  while( SCIPisLE(scip, value, maxactinfvars) )
6183  {
6184  value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6185 
6186  /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6187  if( !SCIPisGE(scip, value2, lhs) )
6188  {
6189  value2 += gcd;
6190  }
6191 
6192  if( SCIPisLE(scip, value2, rhs) )
6193  {
6194  ++nsols;
6195 
6196  /* early termination if we found more than two solutions */
6197  if( nsols == 3 )
6198  break;
6199 
6200  if( minvalue == SCIP_INVALID ) /*lint !e777*/
6201  minvalue = value;
6202 
6203  maxvalue = value;
6204  }
6205  value += gcdinfvars;
6206  }
6207  assert(nsols < 2 || minvalue <= maxvalue);
6208 
6209  /* determine last possible solution for better bounding */
6210  if( nsols == 3 )
6211  {
6212 #ifndef NDEBUG
6213  SCIP_Real secondsolval = maxvalue;
6214 #endif
6215  value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6216 
6217  /* check how many possible solutions exist */
6218  while( SCIPisGE(scip, value, minactinfvars) )
6219  {
6220  value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6221 
6222  /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6223  if( !SCIPisLE(scip, value2, rhs) )
6224  {
6225  value2 -= gcd;
6226  }
6227 
6228  if( SCIPisGE(scip, value2, lhs) )
6229  {
6230  maxvalue = value;
6231  assert(maxvalue > minvalue);
6232  break;
6233  }
6234  value -= gcdinfvars;
6235  }
6236  assert(maxvalue > secondsolval);
6237  }
6238 
6239  SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6240  nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6241 
6242  /* no possible solution found */
6243  if( nsols == 0 )
6244  {
6245  SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6246  gcdinfvars, gcd, lhs, rhs);
6247  SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6248  SCIPdebugPrintCons(scip, cons, NULL);
6249 
6250  /* start conflict analysis */
6251  /* @todo improve conflict analysis by adding relaxed bounds */
6252  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6253 
6254  *cutoff = TRUE;
6255  }
6256  /* if only one solution exist we can extract a new constraint or fix variables */
6257  else if( nsols == 1 )
6258  {
6259  assert(minvalue == maxvalue); /*lint !e777*/
6260 
6261  /* we can fix the only variable in our second set of variables */
6262  if( ninfcheckvars == 1 )
6263  {
6264  SCIP_Bool fixed;
6265 
6266  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6267 
6268  SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6269  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6270  SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6271 
6272  /* fix variable to only possible value */
6273  SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6274  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6275 
6276  if( *cutoff )
6277  {
6278  /* start conflict analysis */
6279  /* @todo improve conflict analysis by adding relaxed bounds */
6280  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6281  }
6282 
6283  if( fixed )
6284  ++(*nfixedvars);
6285  }
6286  else
6287  {
6288  /* check for exactly one unfixed variable which is not part of the infcheckvars */
6289  if( ninfcheckvars == nunfixedvars - 1 )
6290  {
6291  SCIP_Real bound;
6292  SCIP_Bool foundvar = FALSE;
6293  SCIP_Bool fixed;
6294  int w = 0;
6295 
6296  assert(ninfcheckvars > 0);
6297 
6298  /* find variable which is not an infcheckvar and fix it */
6299  for( v = 0; v < consdata->nvars - 1; ++v )
6300  {
6301  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6302  {
6303  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6304  {
6305 #ifndef NDEBUG
6306  int v2 = v + 1;
6307  int w2 = w;
6308 
6309  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6310 
6311  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6312  {
6313  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6314  continue;
6315 
6316  assert(consdata->vars[v2] == infcheckvars[w2]);
6317  ++w2;
6318  }
6319  assert(w2 == ninfcheckvars);
6320 #endif
6321  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6322 
6323  foundvar = TRUE;
6324 
6325  if( consdata->vals[v] < 0 )
6326  {
6327  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6328  }
6329  else
6330  {
6331  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6332  }
6333 
6334  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6335  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6336  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6337 
6338  /* fix variable to only possible value */
6339  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6340  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6341 
6342  if( *cutoff )
6343  {
6344  /* start conflict analysis */
6345  /* @todo improve conflict analysis by adding relaxed bounds */
6346  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6347  consdata->vars[v], bound) );
6348  }
6349 
6350  if( fixed )
6351  ++(*nfixedvars);
6352 
6353  break;
6354  }
6355 
6356  ++w;
6357  }
6358  }
6359 
6360  /* maybe last variable was the not infcheckvar */
6361  if( !foundvar )
6362  {
6363  assert(v == consdata->nvars - 1);
6364  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6365 
6366  if( consdata->vals[v] < 0 )
6367  {
6368  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6369  }
6370  else
6371  {
6372  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6373  }
6374 
6375  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6376  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6377  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6378 
6379  /* fix variable to only possible value */
6380  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6381  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6382 
6383  if( *cutoff )
6384  {
6385  /* start conflict analysis */
6386  /* @todo improve conflict analysis by adding relaxed bounds */
6387  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6388  consdata->vars[v], bound) );
6389  }
6390 
6391  if( fixed )
6392  ++(*nfixedvars);
6393  }
6394  }
6395  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6396  {
6397  /* aggregation possible if we have two variables, but this will be done later on */
6398  SCIP_CONS* newcons;
6399  char name[SCIP_MAXSTRLEN];
6400 
6401  /* create, add, and release new artificial constraint */
6402  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6403  ++conshdlrdata->naddconss;
6404 
6405  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6406 
6407  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6408  maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6409  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6410 
6411  SCIPdebugPrintCons(scip, newcons, NULL);
6412 
6413  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6414 
6415  ++(*naddconss);
6416  }
6417  }
6418  }
6419  /* at least two solutions */
6420  else
6421  {
6422  /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6423 
6424  /* only one variable in the second set, so we can bound this variables */
6425  if( ninfcheckvars == 1 )
6426  {
6427  SCIP_Bool tightened;
6428  SCIP_Real newlb;
6429  SCIP_Real newub;
6430 
6431  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6432 
6433  if( infcheckvals[0] < 0 )
6434  {
6435  newlb = maxvalue/infcheckvals[0];
6436  newub = minvalue/infcheckvals[0];
6437  }
6438  else
6439  {
6440  newlb = minvalue/infcheckvals[0];
6441  newub = maxvalue/infcheckvals[0];
6442  }
6443  assert(newlb < newub);
6444 
6445  if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6446  {
6447  /* update lower bound of variable */
6448  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6449  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6450 
6451  /* tighten variable lower bound to minimal possible value */
6452  SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6453  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6454 
6455  if( *cutoff )
6456  {
6457  /* start conflict analysis */
6458  /* @todo improve conflict analysis by adding relaxed bounds */
6459  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6460  }
6461 
6462  if( tightened )
6463  ++(*nchgbds);
6464  }
6465 
6466  if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6467  {
6468  /* update upper bound of variable */
6469  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6470  SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6471 
6472  /* tighten variable upper bound to maximal possible value */
6473  SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6474  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6475 
6476  if( *cutoff )
6477  {
6478  /* start conflict analysis */
6479  /* @todo improve conflict analysis by adding relaxed bounds */
6480  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6481  }
6482 
6483  if( tightened )
6484  ++(*nchgbds);
6485  }
6486  }
6487  /* check if we have only one not infcheckvars, if so we can tighten this variable */
6488  else if( ninfcheckvars == nunfixedvars - 1 )
6489  {
6490  SCIP_Bool foundvar = FALSE;
6491  SCIP_Bool tightened;
6492  SCIP_Real newlb;
6493  SCIP_Real newub;
6494  int w = 0;
6495 
6496  assert(ninfcheckvars > 0);
6497  assert(minvalue < maxvalue);
6498 
6499  /* find variable which is not an infcheckvar and fix it */
6500  for( v = 0; v < consdata->nvars - 1; ++v )
6501  {
6502  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6503  {
6504  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6505  {
6506 #ifndef NDEBUG
6507  int v2 = v + 1;
6508  int w2 = w;
6509 
6510  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6511 
6512  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6513  {
6514  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6515  continue;
6516 
6517  assert(consdata->vars[v2] == infcheckvars[w2]);
6518  ++w2;
6519  }
6520  assert(w2 == ninfcheckvars);
6521 #endif
6522 
6523  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6524  foundvar = TRUE;
6525 
6526  if( consdata->vals[v] < 0 )
6527  {
6528  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6529  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6530  }
6531  else
6532  {
6533  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6534  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6535  }
6536  assert(SCIPisLE(scip, newlb, newub));
6537 
6538  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6539  {
6540  /* update lower bound of variable */
6541  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6542  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6543 
6544  /* tighten variable lower bound to minimal possible value */
6545  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6546  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6547 
6548  if( *cutoff )
6549  {
6550  /* start conflict analysis */
6551  /* @todo improve conflict analysis by adding relaxed bounds */
6552  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6553  consdata->vars[v], newlb) );
6554  }
6555 
6556  if( tightened )
6557  ++(*nchgbds);
6558  }
6559 
6560  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6561  {
6562  /* update upper bound of variable */
6563  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6564  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6565 
6566  /* tighten variable upper bound to maximal possible value */
6567  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6568  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6569 
6570  if( *cutoff )
6571  {
6572  /* start conflict analysis */
6573  /* @todo improve conflict analysis by adding relaxed bounds */
6574  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6575  consdata->vars[v], newub) );
6576  }
6577 
6578  if( tightened )
6579  ++(*nchgbds);
6580  }
6581 
6582  break;
6583  }
6584 
6585  ++w;
6586  }
6587  }
6588 
6589  /* maybe last variable was the not infcheckvar */
6590  if( !foundvar )
6591  {
6592  assert(v == consdata->nvars - 1);
6593  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6594 
6595  if( consdata->vals[v] < 0 )
6596  {
6597  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6598  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6599  }
6600  else
6601  {
6602  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6603  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6604  }
6605  assert(SCIPisLE(scip, newlb, newub));
6606 
6607  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6608  {
6609  /* update lower bound of variable */
6610  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6611  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6612 
6613  /* tighten variable lower bound to minimal possible value */
6614  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6615  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6616 
6617  if( *cutoff )
6618  {
6619  /* start conflict analysis */
6620  /* @todo improve conflict analysis by adding relaxed bounds */
6621  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6622  }
6623 
6624  if( tightened )
6625  ++(*nchgbds);
6626  }
6627 
6628  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6629  {
6630  /* update upper bound of variable */
6631  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6632  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6633 
6634  /* tighten variable upper bound to maximal possible value */
6635  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6636  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6637 
6638  if( *cutoff )
6639  {
6640  /* start conflict analysis */
6641  /* @todo improve conflict analysis by adding relaxed bounds */
6642  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6643  }
6644 
6645  if( tightened )
6646  ++(*nchgbds);
6647  }
6648  }
6649  }
6650  /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6651  * region for our infcheckvars, if possible
6652  */
6653  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6654  {
6655  SCIP_CONS* newcons;
6656  char name[SCIP_MAXSTRLEN];
6657  SCIP_Real newlhs;
6658  SCIP_Real newrhs;
6659 
6660  assert(maxvalue > minvalue);
6661 
6662  if( SCIPisGT(scip, minvalue, minactinfvars) )
6663  newlhs = minvalue;
6664  else
6665  newlhs = -SCIPinfinity(scip);
6666 
6667  if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6668  newrhs = maxvalue;
6669  else
6670  newrhs = SCIPinfinity(scip);
6671 
6672  if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6673  {
6674  /* create, add, and release new artificial constraint */
6675  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6676  ++conshdlrdata->naddconss;
6677 
6678  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6679 
6680  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6681  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6682  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6683 
6684  SCIPdebugPrintCons(scip, newcons, NULL);
6685  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6686 
6687  ++(*naddconss);
6688  }
6689  /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6690  * should be maxvalue */
6691  }
6692  }
6693  }
6694  }
6695  else if( addartconss && ncontvars < ninfcheckvars )
6696  {
6697  SCIP_Real maxact = 0.0;
6698  SCIP_Real minact = 0.0;
6699  int w = 0;
6700 
6701  /* compute activities of non-infcheckvars */
6702  for( v = 0; v < consdata->nvars; ++v )
6703  {
6704  if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6705  {
6706  ++w;
6707  continue;
6708  }
6709 
6710  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6711  {
6712  if( SCIPvarIsBinary(consdata->vars[v]) )
6713  {
6714  if( consdata->vals[v] > 0.0 )
6715  maxact += consdata->vals[v];
6716  else
6717  minact += consdata->vals[v];
6718  }
6719  else
6720  {
6721  SCIP_Real tmpval;
6722 
6723  assert(SCIPvarIsIntegral(consdata->vars[v]));
6724 
6725  if( consdata->vals[v] > 0.0 )
6726  {
6727  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6728 
6729  if( SCIPisHugeValue(scip, -tmpval) )
6730  break;
6731 
6732  minact += tmpval;
6733 
6734  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6735 
6736  if( SCIPisHugeValue(scip, tmpval) )
6737  break;
6738 
6739  maxact += tmpval;
6740  }
6741  else
6742  {
6743  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6744 
6745  if( SCIPisHugeValue(scip, -tmpval) )
6746  break;
6747 
6748  minact += tmpval;
6749 
6750  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6751 
6752  if( SCIPisHugeValue(scip, tmpval) )
6753  break;
6754 
6755  maxact += tmpval;
6756  }
6757  }
6758  }
6759  }
6760  if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6761  {
6762  SCIP_CONS* newcons;
6763  char name[SCIP_MAXSTRLEN];
6764  SCIP_Real newlhs;
6765  SCIP_Real newrhs;
6766 
6767  assert(maxact > minact);
6768  assert(w == ninfcheckvars);
6769 
6770  newlhs = lhs - maxact;
6771  newrhs = rhs - minact;
6772  assert(newlhs < newrhs);
6773 
6774  /* create, add, and release new artificial constraint */
6775  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6776  ++conshdlrdata->naddconss;
6777 
6778  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6779 
6780  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6781  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6782  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6783 
6784  SCIPdebugPrintCons(scip, newcons, NULL);
6785  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6786 
6787  ++(*naddconss);
6788  }
6789  }
6790 
6791  TERMINATE:
6792  SCIPfreeBufferArray(scip, &infcheckvals);
6793  SCIPfreeBufferArray(scip, &infcheckvars);
6794 
6795  return SCIP_OKAY;
6796 }
6797 
6798 /** tightens bounds of a single variable due to activity bounds */
6799 static
6801  SCIP* scip, /**< SCIP data structure */
6802  SCIP_CONS* cons, /**< linear constraint */
6803  int pos, /**< position of the variable in the vars array */
6804  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6805  int* nchgbds, /**< pointer to count the total number of tightened bounds */
6806  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6807  )
6808 {
6809  SCIP_CONSDATA* consdata;
6810  SCIP_VAR* var;
6811  SCIP_Real val;
6812  SCIP_Real lb;
6813  SCIP_Real ub;
6814  SCIP_Real minresactivity;
6815  SCIP_Real maxresactivity;
6816  SCIP_Real lhs;
6817  SCIP_Real rhs;
6818  SCIP_Bool infeasible;
6819  SCIP_Bool tightened;
6820  SCIP_Bool minisrelax;
6821  SCIP_Bool maxisrelax;
6822  SCIP_Bool isminsettoinfinity;
6823  SCIP_Bool ismaxsettoinfinity;
6824 
6825  assert(scip != NULL);
6826  assert(cons != NULL);
6827  assert(cutoff != NULL);
6828  assert(nchgbds != NULL);
6829 
6830  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6831  if( SCIPconsIsModifiable(cons) )
6832  return SCIP_OKAY;
6833 
6834  consdata = SCIPconsGetData(cons);
6835  assert(consdata != NULL);
6836  assert(0 <= pos && pos < consdata->nvars);
6837 
6838  *cutoff = FALSE;
6839 
6840  var = consdata->vars[pos];
6841 
6842  /* we cannot tighten bounds of multi-aggregated variables */
6844  return SCIP_OKAY;
6845 
6846  val = consdata->vals[pos];
6847  lhs = consdata->lhs;
6848  rhs = consdata->rhs;
6849  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6850  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
6851  assert(var != NULL);
6852  assert(!SCIPisZero(scip, val));
6853  assert(!SCIPisInfinity(scip, lhs));
6854  assert(!SCIPisInfinity(scip, -rhs));
6855 
6856  lb = SCIPvarGetLbLocal(var);
6857  ub = SCIPvarGetUbLocal(var);
6858  assert(SCIPisLE(scip, lb, ub));
6859 
6860  if( val > 0.0 )
6861  {
6862  /* check, if we can tighten the variable's bounds */
6863  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6864  {
6865  SCIP_Real newub;
6866 
6867  newub = (rhs - minresactivity)/val;
6868 
6869  if( !SCIPisInfinity(scip, newub) &&
6870  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6871  {
6872  SCIP_Bool activityunreliable;
6873  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6874 
6875  /* check minresactivities for reliability */
6876  if( activityunreliable )
6877  {
6878  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6879  newub = (rhs - minresactivity)/val;
6880  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6881  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6882  && (!force || !SCIPisLT(scip, newub, ub)));
6883  }
6884 
6885  if( !activityunreliable )
6886  {
6887  /* tighten upper bound */
6888  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6889  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6890  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6891  &infeasible, &tightened) );
6892  if( infeasible )
6893  {
6894  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6895  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6896 
6897  /* analyze conflict */
6898  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6899 
6900  *cutoff = TRUE;
6901  return SCIP_OKAY;
6902  }
6903  if( tightened )
6904  {
6905  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6906  assert(SCIPisFeasLE(scip, ub, newub));
6907  (*nchgbds)++;
6908 
6909  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6910  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6911  }
6912  }
6913  }
6914  }
6915 
6916  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6917  {
6918  SCIP_Real newlb;
6919 
6920  newlb = (lhs - maxresactivity)/val;
6921  if( !SCIPisInfinity(scip, -newlb) &&
6922  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6923  {
6924  /* check maxresactivities for reliability */
6925  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6926  {
6927  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6928  newlb = (lhs - maxresactivity)/val;
6929 
6930  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6931  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6932  && (!force || !SCIPisGT(scip, newlb, lb))) )
6933  return SCIP_OKAY;
6934  }
6935 
6936  /* tighten lower bound */
6937  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6938  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6939  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6940  &infeasible, &tightened) );
6941  if( infeasible )
6942  {
6943  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6944  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6945 
6946  /* analyze conflict */
6947  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6948 
6949  *cutoff = TRUE;
6950  return SCIP_OKAY;
6951  }
6952  if( tightened )
6953  {
6954  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6955  assert(SCIPisFeasGE(scip, lb, newlb));
6956  (*nchgbds)++;
6957  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6958  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6959  }
6960  }
6961  }
6962  }
6963  else
6964  {
6965  /* check, if we can tighten the variable's bounds */
6966  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6967  {
6968  SCIP_Real newlb;
6969 
6970  newlb = (rhs - minresactivity)/val;
6971  if( !SCIPisInfinity(scip, -newlb) &&
6972  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6973  {
6974  SCIP_Bool activityunreliable;
6975  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6976  /* check minresactivities for reliability */
6977  if( activityunreliable )
6978  {
6979  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6980  newlb = (rhs - minresactivity)/val;
6981 
6982  activityunreliable = SCIPisInfinity(scip, -minresactivity)
6983  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6984  && (!force || !SCIPisGT(scip, newlb, lb)));
6985  }
6986 
6987  if( !activityunreliable )
6988  {
6989  /* tighten lower bound */
6990  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6991  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6992  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6993  &infeasible, &tightened) );
6994  if( infeasible )
6995  {
6996  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6997  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6998 
6999  /* analyze conflict */
7000  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7001 
7002  *cutoff = TRUE;
7003  return SCIP_OKAY;
7004  }
7005  if( tightened )
7006  {
7007  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7008  assert(SCIPisFeasGE(scip, lb, newlb));
7009  (*nchgbds)++;
7010  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7011  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7012  }
7013  }
7014  }
7015  }
7016 
7017  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
7018  {
7019  SCIP_Real newub;
7020 
7021  newub = (lhs - maxresactivity)/val;
7022  if( !SCIPisInfinity(scip, newub) &&
7023  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
7024  {
7025  /* check maxresactivities for reliability */
7026  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
7027  {
7028  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
7029  newub = (lhs - maxresactivity)/val;
7030 
7031  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
7032  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
7033  && (!force || !SCIPisLT(scip, newub, ub))) )
7034  return SCIP_OKAY;
7035  }
7036 
7037  /* tighten upper bound */
7038  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
7039  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
7040  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
7041  &infeasible, &tightened) );
7042  if( infeasible )
7043  {
7044  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7045  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
7046 
7047  /* analyze conflict */
7048  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7049 
7050  *cutoff = TRUE;
7051  return SCIP_OKAY;
7052  }
7053  if( tightened )
7054  {
7055  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7056  assert(SCIPisFeasLE(scip, ub, newub));
7057  (*nchgbds)++;
7058  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7059  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7060  }
7061  }
7062  }
7063  }
7064 
7065  return SCIP_OKAY;
7066 }
7067 
7068 #define MAXTIGHTENROUNDS 10
7069 
7070 /** tightens bounds of variables in constraint due to activity bounds */
7071 static
7073  SCIP* scip, /**< SCIP data structure */
7074  SCIP_CONS* cons, /**< linear constraint */
7075  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7076  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7077  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7078  int* nchgbds /**< pointer to count the total number of tightened bounds */
7079  )
7080 {
7081  SCIP_CONSDATA* consdata;
7082  unsigned int tightenmode;
7083  int nvars;
7084  int nrounds;
7085  int lastchange;
7086  int oldnchgbds;
7087 #ifndef SCIP_DEBUG
7088  int oldnchgbdstotal;
7089 #endif
7090  int v;
7091  SCIP_Bool force;
7092  SCIP_Bool easycase;
7093 
7094  assert(scip != NULL);
7095  assert(cons != NULL);
7096  assert(nchgbds != NULL);
7097  assert(cutoff != NULL);
7098 
7099  *cutoff = FALSE;
7100 
7101  /* we cannot tighten variables' bounds, if the constraint may be not complete */
7102  if( SCIPconsIsModifiable(cons) )
7103  return SCIP_OKAY;
7104 
7105  /* if a constraint was created after presolve, then it may hold fixed variables
7106  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7107  * thus, ensure here again that variable fixings have been applied
7108  */
7109  SCIP_CALL( applyFixings(scip, cons, cutoff) );
7110  if( *cutoff )
7111  return SCIP_OKAY;
7112 
7113  /* check if constraint has any chances of tightening bounds */
7114  if( !canTightenBounds(cons) )
7115  return SCIP_OKAY;
7116 
7117  consdata = SCIPconsGetData(cons);
7118  assert(consdata != NULL);
7119 
7120  nvars = consdata->nvars;
7121  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7122 
7123  /* we are at the root node or during presolving */
7124  if( SCIPgetDepth(scip) < 1 )
7125  tightenmode = 2;
7126  else
7127  tightenmode = 1;
7128 
7129  /* stop if we already tightened the constraint and the tightening is not forced */
7130  if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7131  return SCIP_OKAY;
7132 
7133  /* ensure that the variables are properly sorted */
7134  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7135  {
7136  SCIP_CALL( consdataSort(scip, consdata) );
7137  assert(consdata->coefsorted);
7138  }
7139 
7140  /* update maximal activity delta if necessary */
7141  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7142  consdataRecomputeMaxActivityDelta(scip, consdata);
7143 
7144  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7145  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7146  checkMaxActivityDelta(scip, consdata);
7147 
7148  /* this may happen if all variables are fixed */
7149  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7150  return SCIP_OKAY;
7151 
7152  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7153  {
7154  SCIP_Real slack;
7155  SCIP_Real surplus;
7156  SCIP_Real minactivity;
7157  SCIP_Real maxactivity;
7158  SCIP_Bool minisrelax;
7159  SCIP_Bool maxisrelax;
7160  SCIP_Bool isminsettoinfinity;
7161  SCIP_Bool ismaxsettoinfinity;
7162 
7163  /* use maximal activity delta to skip propagation (cannot deduce anything) */
7164  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax,
7165  &isminsettoinfinity, &ismaxsettoinfinity);
7166  assert(!SCIPisInfinity(scip, minactivity));
7167  assert(!SCIPisInfinity(scip, -maxactivity));
7168 
7169  slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7170  surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7171 
7172  /* check if the constraint will propagate */
7173  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7174  return SCIP_OKAY;
7175  }
7176 
7177  /* check if we can use fast implementation for easy and numerically well behaved cases */
7178  easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7179 
7180  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7181  lastchange = -1;
7182  oldnchgbds = 0;
7183 
7184 #ifndef SCIP_DEBUG
7185  oldnchgbdstotal = *nchgbds;
7186 #endif
7187 
7188  for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7189  {
7190  /* ensure that the variables are properly sorted
7191  *
7192  * note: it might happen that integer variables become binary during bound tightening at the root node
7193  */
7194  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7195  {
7196  SCIP_CALL( consdataSort(scip, consdata) );
7197  assert(consdata->coefsorted);
7198  }
7199 
7200  /* mark the constraint to have the variables' bounds tightened */
7201  consdata->boundstightened = (unsigned int)tightenmode;
7202 
7203  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7204  * sorting enables skipping variables
7205  */
7206  v = 0;
7207  while( v < nvars && v != lastchange && !(*cutoff) )
7208  {
7209  oldnchgbds = *nchgbds;
7210 
7211  if( easycase )
7212  {
7213  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7214  }
7215  else
7216  {
7217  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7218  }
7219 
7220  /* if there was no progress, skip the rest of the binary variables */
7221  if( *nchgbds > oldnchgbds )
7222  {
7223  lastchange = v;
7224  ++v;
7225  }
7226  else if( consdata->coefsorted && v < consdata->nbinvars - 1
7227  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7228  v = consdata->nbinvars;
7229  else
7230  ++v;
7231  }
7232 
7233 #ifndef SCIP_DEBUG
7234  SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7235  *nchgbds - oldnchgbdstotal, nrounds);
7236  oldnchgbdstotal += oldnchgbds;
7237 #endif
7238  }
7239 
7240 #ifndef NDEBUG
7241  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7242  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7243 #endif
7244 
7245  return SCIP_OKAY;
7246 }
7247 
7248 /** checks linear constraint for feasibility of given solution or current solution */
7249 static
7251  SCIP* scip, /**< SCIP data structure */
7252  SCIP_CONS* cons, /**< linear constraint */
7253  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7254  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7255  SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7256  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7257  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7258  )
7259 {
7260  SCIP_CONSDATA* consdata;
7261  SCIP_Real activity;
7262  SCIP_Real absviol;
7263  SCIP_Real relviol;
7264  SCIP_Real lhsviol;
7265  SCIP_Real rhsviol;
7266 
7267  assert(scip != NULL);
7268  assert(cons != NULL);
7269  assert(violated != NULL);
7270 
7271  SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7272  SCIPdebugPrintCons(scip, cons, NULL);
7273 
7274  consdata = SCIPconsGetData(cons);
7275  assert(consdata != NULL);
7276 
7277  *violated = FALSE;
7278 
7279  if( consdata->row != NULL )
7280  {
7281  if( !checklprows && SCIProwIsInLP(consdata->row) )
7282  return SCIP_OKAY;
7283  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7284  activity = consdataComputePseudoActivity(scip, consdata);
7285  else
7286  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7287  }
7288  else
7289  activity = consdataGetActivity(scip, consdata, sol);
7290 
7291  SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7292  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7293  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7294  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7295 
7296  /* calculate absolute and relative bound violations */
7297  lhsviol = consdata->lhs - activity;
7298  rhsviol = activity - consdata->rhs;
7299 
7300  absviol = 0.0;
7301  relviol = 0.0;
7302  if( (lhsviol > 0) && (lhsviol > rhsviol) )
7303  {
7304  absviol = lhsviol;
7305  relviol = SCIPrelDiff(consdata->lhs, activity);
7306  }
7307  else if( rhsviol > 0 )
7308  {
7309  absviol = rhsviol;
7310  relviol = SCIPrelDiff(activity, consdata->rhs);
7311  }
7312 
7313  /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7314  * return infeasible for safety
7315  */
7316  if( activity == SCIP_INVALID ) /*lint !e777*/
7317  {
7318  assert(sol == NULL);
7319  *violated = TRUE;
7320 
7321  /* set violation of invalid pseudo solutions */
7322  absviol = SCIP_INVALID;
7323  relviol = SCIP_INVALID;
7324 
7325  /* reset constraint age since we are in enforcement */
7326  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7327  }
7328  /* check with relative tolerances (the default) */
7329  else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7330  {
7331  /* the "normal" check: one of the two sides is violated */
7332  if( !checkrelmaxabs )
7333  {
7334  *violated = TRUE;
7335 
7336  /* only reset constraint age if we are in enforcement */
7337  if( sol == NULL )
7338  {
7339  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7340  }
7341  }
7342  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7343  * small compared to the absolute values occurring in the activity
7344  */
7345  else
7346  {
7347  SCIP_Real maxabs;
7348  SCIP_Real coef;
7349  SCIP_Real absval;
7350  SCIP_Real solval;
7351  int v;
7352 
7353  maxabs = 1.0;
7354 
7355  /* compute maximum absolute value */
7356  for( v = 0; v < consdata->nvars; ++v )
7357  {
7358  if( consdata->vals != NULL )
7359  {
7360  coef = consdata->vals[v];
7361  }
7362  else
7363  coef = 1.0;
7364 
7365  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7366  absval = REALABS( coef * solval );
7367  maxabs = MAX( maxabs, absval );
7368  }
7369 
7370  /* regard left hand side, first */
7371  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7372  {
7373  /* check whether violation is random noise */
7374  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7375  {
7376  SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7377  consdata->lhs - activity, maxabs);
7378  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7379 
7380  /* only increase constraint age if we are in enforcement */
7381  if( sol == NULL )
7382  {
7383  SCIP_CALL( SCIPincConsAge(scip, cons) );
7384  }
7385  }
7386  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7387  else if( SCIPisZero(scip, consdata->lhs) )
7388  {
7389  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7390  {
7391  SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7392  consdata->lhs - activity, maxabs);
7393  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7394 
7395  /* only increase constraint age if we are in enforcement */
7396  if( sol == NULL )
7397  {
7398  SCIP_CALL( SCIPincConsAge(scip, cons) );
7399  }
7400  }
7401  else
7402  {
7403  *violated = TRUE;
7404 
7405  /* only reset constraint age if we are in enforcement */
7406  if( sol == NULL )
7407  {
7408  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7409  }
7410  }
7411  }
7412  else
7413  {
7414  *violated = TRUE;
7415 
7416  /* only reset constraint age if we are in enforcement */
7417  if( sol == NULL )
7418  {
7419  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7420  }
7421  }
7422  }
7423 
7424  /* now regard right hand side */
7425  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7426  {
7427  /* check whether violation is random noise */
7428  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7429  {
7430  SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7431  activity - consdata->rhs, maxabs);
7432  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7433 
7434  /* only increase constraint age if we are in enforcement */
7435  if( sol == NULL )
7436  {
7437  SCIP_CALL( SCIPincConsAge(scip, cons) );
7438  }
7439  }
7440  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7441  else if( SCIPisZero(scip, consdata->rhs) )
7442  {
7443  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7444  {
7445  SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7446  activity - consdata->rhs, maxabs);
7447  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7448 
7449  /* only increase constraint age if we are in enforcement */
7450  if( sol == NULL )
7451  {
7452  SCIP_CALL( SCIPincConsAge(scip, cons) );
7453  }
7454  }
7455  else
7456  {
7457  *violated = TRUE;
7458 
7459  /* only reset constraint age if we are in enforcement */
7460  if( sol == NULL )
7461  {
7462  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7463  }
7464  }
7465  }
7466  else
7467  {
7468  *violated = TRUE;
7469 
7470  /* only reset constraint age if we are in enforcement */
7471  if( sol == NULL )
7472  {
7473  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7474  }
7475  }
7476  }
7477  }
7478  }
7479  /* check with absolute tolerances */
7480  else if( consdata->checkabsolute &&
7481  ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7482  (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
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  else
7493  {
7494  /* only increase constraint age if we are in enforcement */
7495  if( sol == NULL )
7496  {
7497  SCIP_CALL( SCIPincConsAge(scip, cons) );
7498  }
7499  }
7500 
7501  /* update absolute and relative violation of the solution */
7502  if( sol != NULL )
7503  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7504 
7505  return SCIP_OKAY;
7506 }
7507 
7508 /** creates an LP row in a linear constraint data */
7509 static
7511  SCIP* scip, /**< SCIP data structure */
7512  SCIP_CONS* cons /**< linear constraint */
7513  )
7514 {
7515  SCIP_CONSDATA* consdata;
7516 
7517  assert(scip != NULL);
7518  assert(cons != NULL);
7519 
7520  consdata = SCIPconsGetData(cons);
7521  assert(consdata != NULL);
7522  assert(consdata->row == NULL);
7523 
7524  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7526 
7527  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7528 
7529  return SCIP_OKAY;
7530 }
7531 
7532 /** adds linear constraint as cut to the LP */
7533 static
7535  SCIP* scip, /**< SCIP data structure */
7536  SCIP_CONS* cons, /**< linear constraint */
7537  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7538  )
7539 {
7540  SCIP_CONSDATA* consdata;
7541 
7542  assert(scip != NULL);
7543  assert(cons != NULL);
7544 
7545  consdata = SCIPconsGetData(cons);
7546  assert(consdata != NULL);
7547 
7548  if( consdata->row == NULL )
7549  {
7550  if( !SCIPconsIsModifiable(cons) )
7551  {
7552  /* 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
7553  * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7554  */
7555  SCIP_CALL( applyFixings(scip, cons, cutoff) );
7556  if( *cutoff )
7557  return SCIP_OKAY;
7558  }
7559 
7560  /* convert consdata object into LP row */
7561  SCIP_CALL( createRow(scip, cons) );
7562  }
7563  assert(consdata->row != NULL);
7564 
7565  if( consdata->nvars == 0 )
7566  {
7567  SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7568  }
7569 
7570  /* insert LP row as cut */
7571  if( !SCIProwIsInLP(consdata->row) )
7572  {
7573  SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7574  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7575  /* if presolving is turned off, the row might be trivial */
7576  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7577  {
7578  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7579  }
7580 #ifndef NDEBUG
7581  else
7582  {
7583  int pr;
7584  int cr;
7585  SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7586  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7587  assert( pr == 0 || cr == 0 );
7588  }
7589 #endif
7590  }
7591 
7592  return SCIP_OKAY;
7593 }
7594 
7595 /** adds linear constraint as row to the NLP, if not added yet */
7596 static
7598  SCIP* scip, /**< SCIP data structure */
7599  SCIP_CONS* cons /**< linear constraint */
7600  )
7601 {
7602  SCIP_CONSDATA* consdata;
7603 
7604  assert(SCIPisNLPConstructed(scip));
7605 
7606  /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7607  if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7608  return SCIP_OKAY;
7609 
7610  consdata = SCIPconsGetData(cons);
7611  assert(consdata != NULL);
7612 
7613  if( consdata->nlrow == NULL )
7614  {
7615  assert(consdata->lhs <= consdata->rhs);
7617  SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7618  0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7619 
7620  assert(consdata->nlrow != NULL);
7621  }
7622 
7623  if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7624  {
7625  SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7626  }
7627 
7628  return SCIP_OKAY;
7629 }
7630 
7631 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7632 static
7634  SCIP* scip, /**< SCIP data structure */
7635  SCIP_CONS* cons, /**< linear constraint */
7636  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7637  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7638  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7639  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7640  * the ones with non-zero dual value? */
7641  int* ncuts, /**< pointer to add up the number of found cuts */
7642  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7643  )
7644 {
7645  SCIP_CONSDATA* consdata;
7646  SCIP_Bool violated;
7647  int oldncuts;
7648 
7649  assert(scip != NULL);
7650  assert(conshdlrdata != NULL);
7651  assert(cons != NULL);
7652  assert(cutoff != NULL);
7653 
7654  consdata = SCIPconsGetData(cons);
7655  assert(ncuts != NULL);
7656  assert(consdata != NULL);
7657 
7658  oldncuts = *ncuts;
7659  *cutoff = FALSE;
7660 
7661  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7662 
7663  if( violated )
7664  {
7665  /* insert LP row as cut */
7666  SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7667  (*ncuts)++;
7668  }
7669  else if( !SCIPconsIsModifiable(cons) && separatecards )
7670  {
7671  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7672  if( !separateall && sol == NULL )
7673  {
7674  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7675  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7676  {
7677  SCIP_Real dualsol;
7678 
7679  dualsol = SCIProwGetDualsol(consdata->row);
7680  if( SCIPisFeasNegative(scip, dualsol) )
7681  {
7682  if( !SCIPisInfinity(scip, consdata->rhs) )
7683  {
7684  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7685  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7686  }
7687  }
7688  else if( SCIPisFeasPositive(scip, dualsol) )
7689  {
7690  if( !SCIPisInfinity(scip, -consdata->lhs) )
7691  {
7692  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7693  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7694  }
7695  }
7696  }
7697  }
7698  else
7699  {
7700  if( !SCIPisInfinity(scip, consdata->rhs) )
7701  {
7702  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7703  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7704  }
7705  if( !SCIPisInfinity(scip, -consdata->lhs) )
7706  {
7707  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7708  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7709  }
7710  }
7711  }
7712 
7713  if( *ncuts > oldncuts )
7714  {
7715  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7716  }
7717 
7718  return SCIP_OKAY;
7719 }
7720 
7721 /** propagation method for linear constraints */
7722 static
7724  SCIP* scip, /**< SCIP data structure */
7725  SCIP_CONS* cons, /**< linear constraint */
7726  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7727  SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7728  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7729  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7730  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7731  int* nchgbds /**< pointer to count the total number of tightened bounds */
7732  )
7733 {
7734  SCIP_CONSDATA* consdata;
7735  SCIP_Real minactivity;
7736  SCIP_Real maxactivity;
7737  SCIP_Bool minactisrelax;
7738  SCIP_Bool maxactisrelax;
7739  SCIP_Bool isminsettoinfinity;
7740  SCIP_Bool ismaxsettoinfinity;
7741 
7742  assert(scip != NULL);
7743  assert(cons != NULL);
7744  assert(cutoff != NULL);
7745  assert(nchgbds != NULL);
7746 
7747  /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7748 
7749  consdata = SCIPconsGetData(cons);
7750  assert(consdata != NULL);
7751 
7752  if( consdata->eventdata == NULL )
7753  {
7754  SCIP_CONSHDLR* conshdlr;
7755  SCIP_CONSHDLRDATA* conshdlrdata;
7756 
7757  conshdlr = SCIPconsGetHdlr(cons);
7758  assert(conshdlr != NULL);
7759 
7760  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7761  assert(conshdlrdata != NULL);
7762 
7763  /* catch bound change events of variables */
7764  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7765  assert(consdata->eventdata != NULL);
7766  }
7767 
7768  *cutoff = FALSE;
7769 
7770  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7771  if( !SCIPconsIsModifiable(cons) )
7772  {
7773  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7774  if( !SCIPinRepropagation(scip) )
7775  {
7776  SCIP_CALL( SCIPincConsAge(scip, cons) );
7777  }
7778 
7779  /* tighten the variable's bounds */
7780  if( tightenbounds )
7781  {
7782  int oldnchgbds;
7783 
7784  oldnchgbds = *nchgbds;
7785 
7786  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7787 
7788  if( *nchgbds > oldnchgbds )
7789  {
7790  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7791  }
7792  }
7793 
7794  /* propagate ranged rows */
7795  if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7796  {
7797  int nfixedvars;
7798  int naddconss;
7799  SCIPdebug( int oldnchgbds = *nchgbds; )
7800 
7801  nfixedvars = 0;
7802  naddconss = 0;
7803 
7804  SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7805 
7806  if( *cutoff )
7807  {
7808  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7809  }
7810  else
7811  {
7812  SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7813  }
7814 
7815  if( nfixedvars > 0 )
7816  *nchgbds += 2*nfixedvars;
7817  } /*lint !e438*/
7818 
7819  /* check constraint for infeasibility and redundancy */
7820  if( !(*cutoff) )
7821  {
7822  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
7823  &isminsettoinfinity, &ismaxsettoinfinity);
7824 
7825  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7826  {
7827  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7828  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7829 
7830  /* analyze conflict */
7831  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7832 
7833  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7834  *cutoff = TRUE;
7835  }
7836  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7837  {
7838  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7839  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7840 
7841  /* analyze conflict */
7842  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7843 
7844  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7845  *cutoff = TRUE;
7846  }
7847  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7848  {
7849  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7850  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7851 
7852  /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7853  if( consdata->nvars > 0 )
7854  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7855  else
7856  SCIP_CALL( SCIPdelCons(scip, cons) );
7857  }
7858  }
7859  }
7860 
7861  return SCIP_OKAY;
7862 }
7863 
7864 
7865 /*
7866  * Presolving methods
7867  */
7868 
7869 /** converts all variables with fixed domain into FIXED variables */
7870 static
7872  SCIP* scip, /**< SCIP data structure */
7873  SCIP_CONS* cons, /**< linear constraint */
7874  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7875  int* nfixedvars /**< pointer to count the total number of fixed variables */
7876  )
7877 {
7878  SCIP_CONSDATA* consdata;
7879  SCIP_VAR* var;
7880  SCIP_VARSTATUS varstatus;
7881  SCIP_Real lb;
7882  SCIP_Real ub;
7883  SCIP_Bool fixed;
7884  SCIP_Bool infeasible;
7885  int v;
7886 
7887  assert(scip != NULL);
7888  assert(cons != NULL);
7889  assert(cutoff != NULL);
7890  assert(nfixedvars != NULL);
7891 
7892  consdata = SCIPconsGetData(cons);
7893  assert(consdata != NULL);
7894 
7895  for( v = 0; v < consdata->nvars; ++v )
7896  {
7897  assert(consdata->vars != NULL);
7898  var = consdata->vars[v];
7899  varstatus = SCIPvarGetStatus(var);
7900 
7901  if( varstatus != SCIP_VARSTATUS_FIXED )
7902  {
7903  lb = SCIPvarGetLbGlobal(var);
7904  ub = SCIPvarGetUbGlobal(var);
7905  if( SCIPisEQ(scip, lb, ub) )
7906  {
7907  SCIP_Real fixval;
7908 
7909  fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7910  SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7911  SCIPvarGetName(var), lb, ub, fixval);
7912  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7913  if( infeasible )
7914  {
7915  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7916  *cutoff = TRUE;
7917  return SCIP_OKAY;
7918  }
7919  if( fixed )
7920  (*nfixedvars)++;
7921  }
7922  }
7923  }
7924 
7925  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7926 
7927  if( infeasible )
7928  {
7929  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7930  *cutoff = TRUE;
7931  return SCIP_OKAY;
7932  }
7933 
7934  assert(consdata->removedfixings);
7935 
7936  return SCIP_OKAY;
7937 }
7938 
7939 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7940 
7941 /** extracts cliques of the constraint and adds them to SCIP
7942  *
7943  * The following clique extraction mechanism are implemeneted
7944  *
7945  * 1. collect binary variables and sort them in non increasing order, then
7946  *
7947  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7948  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7949  * condition
7950  *
7951  * minactivity + vals[i] + vals[i+1] > rhs
7952  *
7953  * and also add the binary to binary implication also for non-successive variables for which the same argument
7954  * holds
7955  *
7956  * minactivity + vals[i] + vals[j] > rhs
7957  *
7958  * 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
7959  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7960  *
7961  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7962  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7963  * condition
7964  *
7965  * maxactivity + vals[i] + vals[i-1] < lhs
7966  *
7967  * and also add the binary to binary implication also for non-successive variables for which the same argument
7968  * holds
7969  *
7970  * maxactivity + vals[i] + vals[j] < lhs
7971  *
7972  * e.g. you could multiply the above example by -1
7973  *
7974  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7975  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7976  * condition
7977  *
7978  * minactivity - vals[i] - vals[i-1] > rhs
7979  *
7980  * and also add the binary to binary implication also for non-successive variables for which the
7981  * same argument holds
7982  *
7983  * minactivity - vals[i] - vals[j] > rhs
7984  *
7985  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7986  * implication x1 = 0 => x3 = 1
7987  *
7988  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7989  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7990  * condition
7991  *
7992  * maxactivity - vals[i] - vals[i+1] < lhs
7993  *
7994  * and also add the binary to binary implication also for non-successive variables for which the same argument
7995  * holds
7996  *
7997  * maxactivity - vals[i] - vals[j] < lhs
7998  *
7999  * e.g. you could multiply the above example by -1
8000  *
8001  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
8002  * as clique, (this part is done at the end of the method)
8003  *
8004  */
8005 static
8007  SCIP* scip, /**< SCIP data structure */
8008  SCIP_CONS* cons, /**< linear constraint */
8009  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
8010  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
8011  int* nfixedvars, /**< pointer to count number of fixed variables */
8012  int* nchgbds, /**< pointer to count the total number of tightened bounds */
8013  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
8014  )
8015 {
8016  SCIP_VAR** vars;
8017  SCIP_Real* vals;
8018  SCIP_CONSDATA* consdata;
8019  SCIP_Bool lhsclique;
8020  SCIP_Bool rhsclique;
8021  SCIP_Bool finitelhs;
8022  SCIP_Bool finiterhs;
8023  SCIP_Bool finiteminact;
8024  SCIP_Bool finitemaxact;
8025  SCIP_Bool finitenegminact;
8026  SCIP_Bool finitenegmaxact;
8027  SCIP_Bool finiteposminact;
8028  SCIP_Bool finiteposmaxact;
8029  SCIP_Bool infeasible;
8030  SCIP_Bool stopped;
8031  int cliquenonzerosadded;
8032  int v;
8033  int i;
8034  int nposcoefs;
8035  int nnegcoefs;
8036  int nvars;
8037 
8038  assert(scip != NULL);
8039  assert(cons != NULL);
8040  assert(nfixedvars != NULL);
8041  assert(nchgbds != NULL);
8042  assert(cutoff != NULL);
8043  assert(!SCIPconsIsDeleted(cons));
8044 
8045  consdata = SCIPconsGetData(cons);
8046  assert(consdata != NULL);
8047 
8048  if( consdata->nvars < 2 )
8049  return SCIP_OKAY;
8050 
8051  /* add implications if possible
8052  *
8053  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
8054  * maximal absolute contribution and also only if this variable would force all other variables to their bound
8055  * corresponding to the global minimal activity of the constraint
8056  */
8057  if( !consdata->implsadded )
8058  {
8059  /* sort variables by variable type */
8060  SCIP_CALL( consdataSort(scip, consdata) );
8061 
8062  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
8063  * up front, might change sorting correspondingly
8064  */
8065  /* fast abort if no binaries seem to exist
8066  * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
8067  * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
8068  * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
8069  * which is the requirement for consdataSort() to actually resort the variables
8070  * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
8071  */
8072  if( !SCIPvarIsBinary(consdata->vars[0]) )
8073  return SCIP_OKAY;
8074 
8075  nvars = consdata->nvars;
8076  vars = consdata->vars;
8077  vals = consdata->vals;
8078 
8079  /* recompute activities if needed */
8080  if( !consdata->validactivities )
8081  consdataCalcActivities(scip, consdata);
8082  assert(consdata->validactivities);
8083 
8084  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8085  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8086  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8087  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8088  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8089  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8090  finiteminact = (finitenegminact && finiteposminact);
8091  finitemaxact = (finitenegmaxact && finiteposmaxact);
8092 
8093  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8094  {
8095  SCIP_Real maxabscontrib = -1.0;
8096  SCIP_Bool posval = FALSE;
8097  SCIP_Bool allbinary = TRUE;
8098  int oldnchgbds = *nchgbds;
8099  int nbdchgs = 0;
8100  int nimpls = 0;
8101  int position = -1;
8102 
8103  /* we need a valid minimal/maximal activity to add cliques */
8104  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8105  {
8106  consdataRecomputeGlbMinactivity(scip, consdata);
8107  assert(consdata->validglbminact);
8108  }
8109 
8110  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8111  {
8112  consdataRecomputeGlbMaxactivity(scip, consdata);
8113  assert(consdata->validglbmaxact);
8114  }
8115  assert(consdata->validglbminact || consdata->validglbmaxact);
8116 
8117  /* @todo extend this to local/constraint probing */
8118 
8119  /* determine maximal contribution to the activity */
8120  for( v = nvars - 1; v >= 0; --v )
8121  {
8122  if( SCIPvarIsBinary(vars[v]) )
8123  {
8124  if( vals[v] > 0 )
8125  {
8126  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8127 
8128  if( value > maxabscontrib )
8129  {
8130  maxabscontrib = value;
8131  position = v;
8132  posval = TRUE;
8133  }
8134  }
8135  else
8136  {
8137  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8138 
8139  value = REALABS(value);
8140 
8141  if( value > maxabscontrib )
8142  {
8143  maxabscontrib = value;
8144  position = v;
8145  posval = FALSE;
8146  }
8147  }
8148  }
8149  else
8150  allbinary = FALSE;
8151  }
8152  assert(0 <= position && position < nvars);
8153 
8154  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8155  {
8156  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8157  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8158  * implications
8159  */
8160  if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8161  {
8162  for( v = nvars - 1; v >= 0; --v )
8163  {
8164  /* binary to binary implications will be collected when extrating cliques */
8165  if( !SCIPvarIsBinary(vars[v]) )
8166  {
8167  if( v != position )
8168  {
8169  if( vals[v] > 0 )
8170  {
8171  /* add implications */
8172  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8173  ++nimpls;
8174  *nchgbds += nbdchgs;
8175  }
8176  else
8177  {
8178  /* add implications */
8179  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8180  ++nimpls;
8181  *nchgbds += nbdchgs;
8182  }
8183 
8184  if( infeasible )
8185  {
8186  *cutoff = TRUE;
8187  break;
8188  }
8189  }
8190  }
8191  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8192  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8193  break;
8194  }
8195  }
8196 
8197  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8198  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8199  * implications
8200  */
8201  if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8202  {
8203  for( v = nvars - 1; v >= 0; --v )
8204  {
8205  /* binary to binary implications will be collected when extrating cliques */
8206  if( !SCIPvarIsBinary(vars[v]) )
8207  {
8208  if( v != position )
8209  {
8210  if( vals[v] > 0 )
8211  {
8212  /* add implications */
8213  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8214  ++nimpls;
8215  *nchgbds += nbdchgs;
8216  }
8217  else
8218  {
8219  /* add implications */
8220  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8221  ++nimpls;
8222  *nchgbds += nbdchgs;
8223  }
8224 
8225  if( infeasible )
8226  {
8227  *cutoff = TRUE;
8228  break;
8229  }
8230  }
8231  }
8232  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8233  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8234  break;
8235  }
8236  }
8237 
8238  /* did we find some implications */
8239  if( nimpls > 0 )
8240  {
8241  SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8242 
8243  if( *cutoff )
8244  return SCIP_OKAY;
8245 
8246  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8247  if( *nchgbds - oldnchgbds > 0 )
8248  {
8249  /* check for fixed variables */
8250  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8251  if( *cutoff )
8252  return SCIP_OKAY;
8253 
8254  /* tighten variable's bounds */
8255  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8256  if( *cutoff )
8257  return SCIP_OKAY;
8258 
8259  /* check for fixed variables */
8260  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8261  if( *cutoff )
8262  return SCIP_OKAY;
8263  }
8264  }
8265  }
8266  }
8267 
8268  consdata->implsadded = TRUE;
8269  }
8270 
8271  /* check if we already added the cliques of this constraint */
8272  if( consdata->cliquesadded )
8273  return SCIP_OKAY;
8274 
8275  consdata->cliquesadded = TRUE;
8276  cliquenonzerosadded = 0;
8277  stopped = FALSE;
8278 
8279  /* sort variables by variable type */
8280  SCIP_CALL( consdataSort(scip, consdata) );
8281 
8282  nvars = consdata->nvars;
8283  vars = consdata->vars;
8284  vals = consdata->vals;
8285 
8286  /**@todo extract more cliques, implications and variable bounds from linear constraints */
8287 
8288  /* recompute activities if needed */
8289  if( !consdata->validactivities )
8290  consdataCalcActivities(scip, consdata);
8291  assert(consdata->validactivities);
8292 
8293  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8294  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8295  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8296  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8297  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8298  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8299  finiteminact = (finitenegminact && finiteposminact);
8300  finitemaxact = (finitenegmaxact && finiteposmaxact);
8301 
8302  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8303  * information
8304  */
8305  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8306  {
8307  SCIP_VAR** binvars;
8308  SCIP_Real* binvarvals;
8309  int nposbinvars = 0;
8310  int nnegbinvars = 0;
8311  int allonebinary = 0;
8312 
8313  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8314  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8315 
8316  /* collect binary variables */
8317  for( i = 0; i < nvars; ++i )
8318  {
8319  if( SCIPvarIsBinary(vars[i]) )
8320  {
8321  assert(!SCIPisZero(scip, vals[i]));
8322 
8323  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8324  ++allonebinary;
8325 
8326  binvars[nposbinvars + nnegbinvars] = vars[i];
8327  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8328 
8329  if( SCIPisPositive(scip, vals[i]) )
8330  ++nposbinvars;
8331  else
8332  ++nnegbinvars;
8333 
8334  assert(nposbinvars + nnegbinvars <= nvars);
8335  }
8336  /* stop searching for binary variables, because the constraint data is sorted */
8337  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8338  break;
8339  }
8340  assert(nposbinvars + nnegbinvars <= nvars);
8341 
8342  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8343  * cliques
8344  */
8345  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8346  {
8347  SCIP_Real threshold;
8348  int oldnchgbds = *nchgbds;
8349  int nbdchgs;
8350  int jstart;
8351  int j;
8352 
8353  /* we need a valid minimal/maximal activity to add cliques */
8354  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8355  {
8356  consdataRecomputeGlbMinactivity(scip, consdata);
8357  assert(consdata->validglbminact);
8358  }
8359 
8360  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8361  {
8362  consdataRecomputeGlbMaxactivity(scip, consdata);
8363  assert(consdata->validglbmaxact);
8364  }
8365  assert(consdata->validglbminact || consdata->validglbmaxact);
8366 
8367  /* sort coefficients non-increasing to be faster in the clique search */
8368  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8369 
8370  /* case a) */
8371  if( finiterhs && finitenegminact && nposbinvars >= 2 )
8372  {
8373  /* compute value that needs to be exceeded */
8374  threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8375 
8376  j = 1;
8377 #ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8378  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8379  assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8380 #endif
8381  /* check if at least two variables are in a clique */
8382  if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8383  {
8384  ++j;
8385  /* check for extending the clique */
8386  while( j < nposbinvars )
8387  {
8388  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8389  break;
8390  ++j;
8391  }
8392  assert(j >= 2);
8393 
8394  /* add clique with at least two variables */
8395  SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8396 
8397  if( infeasible )
8398  *cutoff = TRUE;
8399 
8400  *nchgbds += nbdchgs;
8401 
8402  cliquenonzerosadded += j;
8403  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8404  stopped = TRUE;
8405 
8406  /* exchange the last variable in the clique if possible and add all new ones */
8407  if( !stopped && !(*cutoff) && j < nposbinvars )
8408  {
8409  SCIP_VAR** clqvars;
8410  int lastfit = j - 2;
8411  assert(lastfit >= 0);
8412 
8413  /* copy all 'main'-clique variables */
8414  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8415 
8416  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8417  while( lastfit >= 0 && j < nposbinvars )
8418  {
8419  /* check if two variables are in a clique */
8420  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8421  {
8422  clqvars[lastfit + 1] = binvars[j];
8423 
8424  /* add clique with at least two variables */
8425  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8426 
8427  if( infeasible )
8428  {
8429  *cutoff = TRUE;
8430  break;
8431  }
8432 
8433  *nchgbds += nbdchgs;
8434 
8435  cliquenonzerosadded += (lastfit + 2);
8436  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8437  {
8438  stopped = TRUE;
8439  break;
8440  }
8441 
8442  ++j;
8443  }
8444  else
8445  --lastfit;
8446  }
8447 
8448  SCIPfreeBufferArray(scip, &clqvars);
8449  }
8450  }
8451  }
8452 
8453  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8454  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8455  {
8456  /* check for fixed variables */
8457  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8458 
8459  if( !*cutoff )
8460  {
8461  /* tighten variable's bounds */
8462  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8463 
8464  if( !*cutoff )
8465  {
8466  /* check for fixed variables */
8467  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8468 
8469  if( !*cutoff )
8470  {
8471  /* sort variables by variable type */
8472  SCIP_CALL( consdataSort(scip, consdata) );
8473 
8474  /* recompute activities if needed */
8475  if( !consdata->validactivities )
8476  consdataCalcActivities(scip, consdata);
8477  assert(consdata->validactivities);
8478 
8479  nvars = consdata->nvars;
8480  vars = consdata->vars;
8481  vals = consdata->vals;
8482  nposbinvars = 0;
8483  nnegbinvars = 0;
8484  allonebinary = 0;
8485 
8486  /* update binary variables */
8487  for( i = 0; i < nvars; ++i )
8488  {
8489  if( SCIPvarIsBinary(vars[i]) )
8490  {
8491  assert(!SCIPisZero(scip, vals[i]));
8492 
8493  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8494  ++allonebinary;
8495 
8496  binvars[nposbinvars + nnegbinvars] = vars[i];
8497  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8498 
8499  if( SCIPisPositive(scip, vals[i]) )
8500  ++nposbinvars;
8501  else
8502  ++nnegbinvars;
8503 
8504  assert(nposbinvars + nnegbinvars <= nvars);
8505  }
8506  /* stop searching for binary variables, because the constraint data is sorted */
8507  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8508  break;
8509  }
8510  assert(nposbinvars + nnegbinvars <= nvars);
8511  }
8512  }
8513  }
8514 
8515  oldnchgbds = *nchgbds;
8516  }
8517 
8518  /* case b) */
8519  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8520  {
8521  /* compute value that needs to be deceeded */
8522  threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8523 
8524  i = nposbinvars + nnegbinvars - 1;
8525  j = i - 1;
8526 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8527  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8528  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8529 #endif
8530  /* check if two variables are in a clique */
8531  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8532  {
8533  --j;
8534  /* check for extending the clique */
8535  while( j >= nposbinvars )
8536  {
8537  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8538  break;
8539  --j;
8540  }
8541  jstart = j;
8542 
8543  assert(i - j >= 2);
8544  /* add clique with at least two variables */
8545  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8546 
8547  if( infeasible )
8548  *cutoff = TRUE;
8549 
8550  *nchgbds += nbdchgs;
8551 
8552  cliquenonzerosadded += (i - j);
8553  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8554  stopped = TRUE;
8555 
8556  /* exchange the last variable in the clique if possible and add all new ones */
8557  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8558  {
8559  SCIP_VAR** clqvars;
8560  int lastfit = jstart + 1;
8561  assert(lastfit < i);
8562 
8563  /* copy all 'main'-clique variables */
8564  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8565  ++lastfit;
8566 
8567  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8568  while( lastfit <= i && j >= nposbinvars )
8569  {
8570  /* check if two variables are in a clique */
8571  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8572  {
8573  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8574  clqvars[lastfit - jstart - 2] = binvars[j];
8575 
8576  assert(i - lastfit + 2 >= 2);
8577  /* add clique with at least two variables */
8578  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8579 
8580  if( infeasible )
8581  {
8582  *cutoff = TRUE;
8583  break;
8584  }
8585 
8586  *nchgbds += nbdchgs;
8587 
8588  cliquenonzerosadded += (i - lastfit + 2);
8589  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8590  {
8591  stopped = TRUE;
8592  break;
8593  }
8594 
8595  --j;
8596  }
8597  else
8598  ++lastfit;
8599  }
8600 
8601  SCIPfreeBufferArray(scip, &clqvars);
8602  }
8603  }
8604  }
8605 
8606  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8607  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8608  {
8609  /* check for fixed variables */
8610  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8611 
8612  if( !*cutoff )
8613  {
8614  /* tighten variable's bounds */
8615  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8616 
8617  if( !*cutoff )
8618  {
8619  /* check for fixed variables */
8620  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8621 
8622  if( !*cutoff )
8623  {
8624  /* sort variables by variable type */
8625  SCIP_CALL( consdataSort(scip, consdata) );
8626 
8627  /* recompute activities if needed */
8628  if( !consdata->validactivities )
8629  consdataCalcActivities(scip, consdata);
8630  assert(consdata->validactivities);
8631 
8632  nvars = consdata->nvars;
8633  vars = consdata->vars;
8634  vals = consdata->vals;
8635  nposbinvars = 0;
8636  nnegbinvars = 0;
8637  allonebinary = 0;
8638 
8639  /* update binary variables */
8640  for( i = 0; i < nvars; ++i )
8641  {
8642  if( SCIPvarIsBinary(vars[i]) )
8643  {
8644  assert(!SCIPisZero(scip, vals[i]));
8645 
8646  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8647  ++allonebinary;
8648 
8649  binvars[nposbinvars + nnegbinvars] = vars[i];
8650  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8651 
8652  if( SCIPisPositive(scip, vals[i]) )
8653  ++nposbinvars;
8654  else
8655  ++nnegbinvars;
8656 
8657  assert(nposbinvars + nnegbinvars <= nvars);
8658  }
8659  /* stop searching for binary variables, because the constraint data is sorted */
8660  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8661  break;
8662  }
8663  assert(nposbinvars + nnegbinvars <= nvars);
8664  }
8665  }
8666  }
8667 
8668  oldnchgbds = *nchgbds;
8669  }
8670 
8671  /* case c) */
8672  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8673  {
8674  SCIP_Bool* values;
8675 
8676  /* initialize clique values array for adding a negated clique */
8677  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8678  BMSclearMemoryArray(values, nnegbinvars);
8679 
8680  /* compute value that needs to be exceeded */
8681  threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8682 
8683  i = nposbinvars + nnegbinvars - 1;
8684  j = i - 1;
8685 
8686 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8687  /* check if the variable should not have already been fixed to one */
8688  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8689 #endif
8690 
8691  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8692  {
8693  --j;
8694  /* check for extending the clique */
8695  while( j >= nposbinvars )
8696  {
8697  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8698  break;
8699  --j;
8700  }
8701  jstart = j;
8702 
8703  assert(i - j >= 2);
8704  /* add negated clique with at least two variables */
8705  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8706 
8707  if( infeasible )
8708  *cutoff = TRUE;
8709 
8710  *nchgbds += nbdchgs;
8711 
8712  cliquenonzerosadded += (i - j);
8713  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8714  stopped = TRUE;
8715 
8716  /* exchange the last variable in the clique if possible and add all new ones */
8717  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8718  {
8719  SCIP_VAR** clqvars;
8720  int lastfit = j + 1;
8721  assert(lastfit < i);
8722 
8723  /* copy all 'main'-clique variables */
8724  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8725  ++lastfit;
8726 
8727  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8728  while( lastfit <= i && j >= nposbinvars )
8729  {
8730  /* check if two variables are in a negated clique */
8731  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8732  {
8733  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8734  clqvars[lastfit - jstart - 2] = binvars[j];
8735 
8736  assert(i - lastfit + 2 >= 2);
8737  /* add clique with at least two variables */
8738  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8739 
8740  if( infeasible )
8741  {
8742  *cutoff = TRUE;
8743  break;
8744  }
8745 
8746  *nchgbds += nbdchgs;
8747 
8748  cliquenonzerosadded += (i - lastfit + 2);
8749  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8750  {
8751  stopped = TRUE;
8752  break;
8753  }
8754 
8755  --j;
8756  }
8757  else
8758  ++lastfit;
8759  }
8760 
8761  SCIPfreeBufferArray(scip, &clqvars);
8762  }
8763  }
8764 
8765  SCIPfreeBufferArray(scip, &values);
8766  }
8767 
8768  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8769  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8770  {
8771  /* check for fixed variables */
8772  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8773 
8774  if( !*cutoff )
8775  {
8776  /* tighten variable's bounds */
8777  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8778 
8779  if( !*cutoff )
8780  {
8781  /* check for fixed variables */
8782  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8783 
8784  if( !*cutoff )
8785  {
8786  /* sort variables by variable type */
8787  SCIP_CALL( consdataSort(scip, consdata) );
8788 
8789  /* recompute activities if needed */
8790  if( !consdata->validactivities )
8791  consdataCalcActivities(scip, consdata);
8792  assert(consdata->validactivities);
8793 
8794  nvars = consdata->nvars;
8795  vars = consdata->vars;
8796  vals = consdata->vals;
8797  nposbinvars = 0;
8798  nnegbinvars = 0;
8799  allonebinary = 0;
8800 
8801  /* update binary variables */
8802  for( i = 0; i < nvars; ++i )
8803  {
8804  if( SCIPvarIsBinary(vars[i]) )
8805  {
8806  assert(!SCIPisZero(scip, vals[i]));
8807 
8808  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8809  ++allonebinary;
8810 
8811  binvars[nposbinvars + nnegbinvars] = vars[i];
8812  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8813 
8814  if( SCIPisPositive(scip, vals[i]) )
8815  ++nposbinvars;
8816  else
8817  ++nnegbinvars;
8818 
8819  assert(nposbinvars + nnegbinvars <= nvars);
8820  }
8821  /* stop searching for binary variables, because the constraint data is sorted */
8822  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8823  break;
8824  }
8825  assert(nposbinvars + nnegbinvars <= nvars);
8826  }
8827  }
8828  }
8829  }
8830 
8831  /* case d) */
8832  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8833  {
8834  SCIP_Bool* values;
8835 
8836  /* initialize clique values array for adding a negated clique */
8837  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8838  BMSclearMemoryArray(values, nposbinvars);
8839 
8840  /* compute value that needs to be exceeded */
8841  threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8842 
8843  j = 1;
8844 
8845 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8846  /* check if the variable should not have already been fixed to one */
8847  assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8848 #endif
8849 
8850  if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8851  {
8852  ++j;
8853  /* check for extending the clique */
8854  while( j < nposbinvars )
8855  {
8856  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8857  break;
8858  ++j;
8859  }
8860  assert(j >= 2);
8861 
8862  /* add negated clique with at least two variables */
8863  SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8864 
8865  if( infeasible )
8866  *cutoff = TRUE;
8867 
8868  *nchgbds += nbdchgs;
8869 
8870  cliquenonzerosadded += j;
8871  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8872  stopped = TRUE;
8873 
8874  /* exchange the last variable in the clique if possible and add all new ones */
8875  if( !stopped && !(*cutoff) && j < nposbinvars )
8876  {
8877  SCIP_VAR** clqvars;
8878  int lastfit = j - 2;
8879  assert(lastfit >= 0);
8880 
8881  /* copy all 'main'-clique variables */
8882  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8883 
8884  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8885  while( lastfit >= 0 && j < nposbinvars )
8886  {
8887  /* check if two variables are in a negated clique */
8888  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8889  {
8890  clqvars[lastfit + 1] = binvars[j];
8891 
8892  /* add clique with at least two variables */
8893  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8894 
8895  if( infeasible )
8896  {
8897  *cutoff = TRUE;
8898  break;
8899  }
8900 
8901  *nchgbds += nbdchgs;
8902 
8903  cliquenonzerosadded += lastfit + 2;
8904  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8905  break;
8906 
8907  ++j;
8908  }
8909  else
8910  --lastfit;
8911  }
8912 
8913  SCIPfreeBufferArray(scip, &clqvars);
8914  }
8915  }
8916 
8917  SCIPfreeBufferArray(scip, &values);
8918  }
8919  }
8920 
8921  SCIPfreeBufferArray(scip, &binvarvals);
8922  SCIPfreeBufferArray(scip, &binvars);
8923 
8924  if( *cutoff )
8925  return SCIP_OKAY;
8926  }
8927 
8928  /* 2. we only check if the constraint is a set packing / partitioning constraint */
8929 
8930  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8931  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8932  */
8933  nposcoefs = 0;
8934  nnegcoefs = 0;
8935  for( i = 0; i < nvars; ++i )
8936  {
8937  if( !SCIPvarIsBinary(vars[i]) )
8938  return SCIP_OKAY;
8939  else if( SCIPisEQ(scip, vals[i], +1.0) )
8940  nposcoefs++;
8941  else if( SCIPisEQ(scip, vals[i], -1.0) )
8942  nnegcoefs++;
8943  else
8944  return SCIP_OKAY;
8945  }
8946 
8947  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8948  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8949 
8950  if( lhsclique || rhsclique )
8951  {
8952  SCIP_Bool* values;
8953  int nbdchgs;
8954 
8955  SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8956  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8957  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8958 
8959  for( i = 0; i < nvars; ++i )
8960  values[i] = (rhsclique == (vals[i] > 0.0));
8961 
8962  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8963 
8964  if( infeasible )
8965  *cutoff = TRUE;
8966 
8967  *nchgbds += nbdchgs;
8968  SCIPfreeBufferArray(scip, &values);
8969  }
8970 
8971  return SCIP_OKAY;
8972 }
8973 
8974 /** tightens left and right hand side of constraint due to integrality */
8975 static
8977  SCIP* scip, /**< SCIP data structure */
8978  SCIP_CONS* cons, /**< linear constraint */
8979  int* nchgsides, /**< pointer to count number of side changes */
8980  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8981  )
8982 {
8983  SCIP_CONSDATA* consdata;
8984  SCIP_Real newlhs;
8985  SCIP_Real newrhs;
8986  SCIP_Bool chglhs;
8987  SCIP_Bool chgrhs;
8988  SCIP_Bool integral;
8989  int i;
8990 
8991  assert(scip != NULL);
8992  assert(cons != NULL);
8993  assert(nchgsides != NULL);
8994  assert(infeasible != NULL);
8996  consdata = SCIPconsGetData(cons);
8997  assert(consdata != NULL);
8998 
8999  *infeasible = FALSE;
9000 
9001  chglhs = FALSE;
9002  chgrhs = FALSE;
9003  newlhs = -SCIPinfinity(scip);
9004  newrhs = SCIPinfinity(scip);
9005 
9006  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
9007  {
9008  integral = TRUE;
9009  for( i = 0; i < consdata->nvars && integral; ++i )
9010  {
9011  integral = SCIPisIntegral(scip, consdata->vals[i])
9012  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
9013  }
9014  if( integral )
9015  {
9016  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
9017  {
9018  newlhs = SCIPfeasCeil(scip, consdata->lhs);
9019  chglhs = TRUE;
9020  }
9021  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
9022  {
9023  newrhs = SCIPfeasFloor(scip, consdata->rhs);
9024  chgrhs = TRUE;
9025  }
9026 
9027  /* check whether rounding would lead to an unsatisfiable constraint */
9028  if( SCIPisGT(scip, newlhs, newrhs) )
9029  {
9030  SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
9031  "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
9032 
9033  *infeasible = TRUE;
9034  return SCIP_OKAY;
9035  }
9036 
9037  SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
9038  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9039 
9040  if( chglhs )
9041  {
9042  assert(!SCIPisInfinity(scip, -newlhs));
9043 
9044  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9045  if( !consdata->upgraded )
9046  (*nchgsides)++;
9047  }
9048  if( chgrhs )
9049  {
9050  assert(!SCIPisInfinity(scip, newrhs));
9051 
9052  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9053  if( !consdata->upgraded )
9054  (*nchgsides)++;
9055  }
9056  SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
9057  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9058  }
9059  }
9060 
9061  return SCIP_OKAY;
9062 }
9063 
9064 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
9065  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
9066  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
9067  * (i) ai >= 0:
9068  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
9069  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
9070  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9071  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9072  * - change coefficients:
9073  * ai' := max(lhs - minact, maxact - rhs)
9074  * lhs' := lhs - (ai - ai')*li
9075  * rhs' := rhs - (ai - ai')*ui
9076  * (ii) ai < 0:
9077  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9078  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9079  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9080  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9081  * - change coefficients:
9082  * ai' := min(rhs - maxact, minact - lhs)
9083  * lhs' := lhs - (ai - ai')*ui
9084  * rhs' := rhs - (ai - ai')*li
9085  *
9086  * We further try to remove redundant variable from the constraint;
9087  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
9088  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9089  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
9090  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
9091  * 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
9092  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
9093  *
9094  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9095  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9096  */
9097 static
9099  SCIP* scip, /**< SCIP data structure */
9100  SCIP_CONS* cons, /**< linear constraint */
9101  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9102  int* nchgsides /**< pointer to count number of side changes */
9103  )
9104 {
9105  SCIP_CONSDATA* consdata;
9106  SCIP_VAR* var;
9107  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9108  * activity, ignoring the coefficients contributing with infinite value */
9109  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9110  * activity, ignoring the coefficients contributing with infinite value */
9111  SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
9112  SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
9113  SCIP_Bool isminsettoinfinity;
9114  SCIP_Bool ismaxsettoinfinity;
9115  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
9116  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
9117  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
9118  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
9119  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9120  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9121  SCIP_Real val;
9122  SCIP_Real newval;
9123  SCIP_Real newlhs;
9124  SCIP_Real newrhs;
9125  SCIP_Real lb;
9126  SCIP_Real ub;
9127  int i;
9128 
9129  assert(scip != NULL);
9130  assert(cons != NULL);
9131  assert(nchgcoefs != NULL);
9132  assert(nchgsides != NULL);
9133 
9134  consdata = SCIPconsGetData(cons);
9135  assert(consdata != NULL);
9136 
9137  /* @todo Is this still needed with automatic recomputation of activities? */
9138  /* if the maximal coefficient is too large, recompute the activities */
9139  if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9140  || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9141  {
9142  consdataRecomputeMinactivity(scip, consdata);
9143  consdataRecomputeMaxactivity(scip, consdata);
9144  }
9145 
9146  /* get the minimal and maximal activity of the constraint */
9147  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9148  &isminsettoinfinity, &ismaxsettoinfinity);
9149 
9150  minleftactivity = 0.0;
9151  maxleftactivity = 0.0;
9152 
9153  /* try to tighten each coefficient */
9154  i = 0;
9155  while( i < consdata->nvars )
9156  {
9157  var = consdata->vars[i];
9158 
9159  /* get coefficient and variable's bounds */
9160  lb = SCIPvarGetLbLocal(var);
9161  ub = SCIPvarGetUbLocal(var);
9162  val = consdata->vals[i];
9163  assert(!SCIPisZero(scip, val));
9164 
9165  /* check sign of coefficient */
9166  if( val >= 0.0 )
9167  {
9168  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9170  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
9171  {
9172  /* change coefficients:
9173  * ai' := max(lhs - minact, maxact - rhs)
9174  * lhs' := lhs - (ai - ai')*li
9175  * rhs' := rhs - (ai - ai')*ui
9176  */
9177 
9178  lval = consdata->lhs - minactivity;
9179  rval = maxactivity - consdata->rhs;
9180 
9181  /* Try to avoid cancellation, if there are only two variables */
9182  if( consdata->nvars == 2 )
9183  {
9184  SCIP_Real otherval;
9185  otherval = consdata->vals[1-i];
9186 
9187  if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9188  {
9189  lval = consdata->lhs - val*lb;
9190  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9191  }
9192 
9193  if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9194  {
9195  rval = val*ub - consdata->rhs;
9196  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9197  }
9198  }
9199 
9200  newval = MAX(lval, rval);
9201  assert(SCIPisSumRelLE(scip, newval, val));
9202 
9203  /* Try to avoid cancellation in computation of lhs/rhs */
9204  newlhs = consdata->lhs - val * lb;
9205  newlhs += newval * lb;
9206  newrhs = consdata->rhs - val * ub;
9207  newrhs += newval * ub;
9208 
9209  if( !SCIPisSumRelEQ(scip, newval, val) )
9210  {
9211  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9212  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9213  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9214 
9215  /* update the coefficient and the activity bounds */
9216  if( SCIPisZero(scip, newval) )
9217  {
9218  SCIP_CALL( delCoefPos(scip, cons, i) );
9219  i--;
9220  }
9221  else
9222  {
9223  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9224  }
9225  (*nchgcoefs)++;
9226 
9227  /* get the new minimal and maximal activity of the constraint */
9228  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9229  &isminsettoinfinity, &ismaxsettoinfinity);
9230 
9231  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9232  {
9233  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9234 
9235  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9236  (*nchgsides)++;
9237  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9238  }
9239 
9240  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9241  {
9242  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9243 
9244  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9245  (*nchgsides)++;
9246  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9247  }
9248  }
9249  }
9250  else
9251  {
9252  if( !SCIPisInfinity(scip, -minleftactivity) )
9253  {
9254  assert(!SCIPisInfinity(scip, val));
9255  assert(!SCIPisInfinity(scip, lb));
9256  if( SCIPisInfinity(scip, -lb) )
9257  minleftactivity = -SCIPinfinity(scip);
9258  else
9259  minleftactivity += val * lb;
9260  }
9261 
9262  if( !SCIPisInfinity(scip, maxleftactivity) )
9263  {
9264  assert(!SCIPisInfinity(scip, val));
9265  assert(!SCIPisInfinity(scip, -ub));
9266  if( SCIPisInfinity(scip,ub) )
9267  maxleftactivity = SCIPinfinity(scip);
9268  else
9269  maxleftactivity += val * ub;
9270  }
9271  }
9272  }
9273  else
9274  {
9275  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9277  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9278  {
9279  /* change coefficients:
9280  * ai' := min(rhs - maxact, minact - lhs)
9281  * lhs' := lhs - (ai - ai')*ui
9282  * rhs' := rhs - (ai - ai')*li
9283  */
9284 
9285  lval = minactivity - consdata->lhs;
9286  rval = consdata->rhs - maxactivity;
9287 
9288  /* Try to avoid cancellation, if there are only two variables */
9289  if( consdata->nvars == 2 )
9290  {
9291  SCIP_Real otherval;
9292  otherval = consdata->vals[1-i];
9293 
9294  if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9295  {
9296  lval = val*ub - consdata->lhs;
9297  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9298  }
9299 
9300  if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9301  {
9302  rval = consdata->rhs - val*lb;
9303  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9304  }
9305  }
9306 
9307  newval = MIN(lval, rval);
9308  assert(SCIPisSumRelGE(scip, newval, val));
9309 
9310  /* Try to avoid cancellation in computation of lhs/rhs */
9311  newlhs = consdata->lhs - val * ub;
9312  newlhs += newval * ub;
9313  newrhs = consdata->rhs - val * lb;
9314  newrhs += newval * lb;
9315 
9316  if( !SCIPisSumRelEQ(scip, newval, val) )
9317  {
9318  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9319  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9320  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9321 
9322  /* update the coefficient and the activity bounds */
9323  if( SCIPisZero(scip, newval) )
9324  {
9325  SCIP_CALL( delCoefPos(scip, cons, i) );
9326  i--;
9327  }
9328  else
9329  {
9330  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9331  }
9332  (*nchgcoefs)++;
9333 
9334  /* get the new minimal and maximal activity of the constraint */
9335  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9336  &isminsettoinfinity, &ismaxsettoinfinity);
9337 
9338  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9339  {
9340  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9341 
9342  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9343  (*nchgsides)++;
9344  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9345  }
9346 
9347  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9348  {
9349  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9350 
9351  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9352  (*nchgsides)++;
9353  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9354  }
9355  }
9356  }
9357  else
9358  {
9359  if( !SCIPisInfinity(scip, -minleftactivity) )
9360  {
9361  assert(!SCIPisInfinity(scip, -val));
9362  assert(!SCIPisInfinity(scip, -ub));
9363  if( SCIPisInfinity(scip, ub) )
9364  minleftactivity = -SCIPinfinity(scip);
9365  else
9366  minleftactivity += val * ub;
9367  }
9368 
9369  if( !SCIPisInfinity(scip, maxleftactivity) )
9370  {
9371  assert(!SCIPisInfinity(scip, -val));
9372  assert(!SCIPisInfinity(scip, lb));
9373  if( SCIPisInfinity(scip, -lb) )
9374  maxleftactivity = SCIPinfinity(scip);
9375  else
9376  maxleftactivity += val * lb;
9377  }
9378  }
9379  }
9380  ++i;
9381  }
9382 
9383  SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9384  minleftactivity, consdata->rhs);
9385  SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9386  maxleftactivity, consdata->lhs);
9387 
9388  /* minleft == \infty ==> minactivity == \infty */
9389  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9390  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9391 
9392  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9393  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9394  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9395  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9396  */
9397  assert(!SCIPisInfinity(scip, minactivity));
9398  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9399  return SCIP_OKAY;
9400 
9401  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9402  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9403  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9404  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9405  */
9406  assert(!SCIPisInfinity(scip, -maxactivity));
9407  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9408  return SCIP_OKAY;
9409 
9410  /* correct lhs and rhs by min/max activity of surely non-redundant variables
9411  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9412  */
9413  aggrlhs = consdata->lhs - minactivity + minleftactivity;
9414  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9415 
9416  /* check if the constraint contains variables which are redundant. The reasoning is the following:
9417  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9418  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9419  * they can be removed from the constraint.
9420  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9421  */
9422  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9423  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9424  {
9425  SCIP_Real minleftactivitypart;
9426  SCIP_Real maxleftactivitypart;
9427 
9428  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9429 
9430  /* try to remove redundant variables from constraint */
9431  i = 0;
9432  while( i < consdata->nvars )
9433  {
9434  var = consdata->vars[i];
9435  minleftactivitypart = 0.0;
9436  maxleftactivitypart = 0.0;
9437  lb = SCIPvarGetLbLocal(var);
9438  ub = SCIPvarGetUbLocal(var);
9439 
9440  /* get coefficient and variable's bounds */
9441  val = consdata->vals[i];
9442  assert(!SCIPisZero(scip, val));
9443 
9444  /* check sign of coefficient */
9445  if( val >= 0.0 )
9446  {
9447  /* negation of condition above in case of positive val */
9449  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9450  {
9451  SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9452  SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9453  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9454  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9455 
9456  minleftactivitypart = val * lb;
9457  maxleftactivitypart = val * ub;
9458 
9459  SCIP_CALL( delCoefPos(scip, cons, i) );
9460  i--;
9461 
9462  /* get the new minimal and maximal activity of the constraint */
9463  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9464  &isminsettoinfinity, &ismaxsettoinfinity);
9465 
9466  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9467  * huge contributions
9468  */
9469  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9470  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9471  }
9472  }
9473  else
9474  {
9475  /* negation of condition above in case of negative val */
9477  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9478  {
9479  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9480  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9481 
9482  minleftactivitypart = val * ub;
9483  maxleftactivitypart = val * lb;
9484 
9485  SCIP_CALL( delCoefPos(scip, cons, i) );
9486  i--;
9487 
9488  /* get the new minimal and maximal activity of the constraint */
9489  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9490  &isminsettoinfinity, &ismaxsettoinfinity);
9491 
9492  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9493  * huge contributions
9494  */
9495  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9496  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9497  }
9498  }
9499 
9500  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9501  * redundant variables could get deleted,
9502  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9503  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9504  * we would also delete y2 and as a result we would have gotten infeasibility */
9505  /* adjust lhs and right hand side */
9506  newlhs = consdata->lhs - minleftactivitypart;
9507  newrhs = consdata->rhs - maxleftactivitypart;
9508 
9509  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9510  {
9511  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9512  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9513  ++(*nchgsides);
9514  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9515  }
9516  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9517  {
9518  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9519  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9520  ++(*nchgsides);
9521  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9522  }
9523  ++i;
9524  }
9525  }
9526 
9527  return SCIP_OKAY;
9528 }
9529 
9530 /** processes equality with only one variable by fixing the variable and deleting the constraint */
9531 static
9533  SCIP* scip, /**< SCIP data structure */
9534  SCIP_CONS* cons, /**< linear constraint */
9535  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9536  int* nfixedvars, /**< pointer to count number of fixed variables */
9537  int* ndelconss /**< pointer to count number of deleted constraints */
9538  )
9539 {
9540  SCIP_CONSDATA* consdata;
9541  SCIP_VAR* var;
9542  SCIP_Real val;
9543  SCIP_Real fixval;
9544  SCIP_Bool infeasible;
9545  SCIP_Bool fixed;
9546 
9547  assert(scip != NULL);
9548  assert(cons != NULL);
9549  assert(cutoff != NULL);
9550  assert(nfixedvars != NULL);
9551  assert(ndelconss != NULL);
9552 
9553  consdata = SCIPconsGetData(cons);
9554  assert(consdata != NULL);
9555  assert(consdata->nvars == 1);
9556  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9557 
9558  /* calculate the value to fix the variable to */
9559  var = consdata->vars[0];
9560  val = consdata->vals[0];
9561  assert(!SCIPisZero(scip, val));
9562  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9563  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9564  SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9565  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9566 
9567  /* fix variable */
9568  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9569  if( infeasible )
9570  {
9571  SCIPdebugMsg(scip, " -> infeasible fixing\n");
9572  *cutoff = TRUE;
9573  return SCIP_OKAY;
9574  }
9575  if( fixed )
9576  (*nfixedvars)++;
9577 
9578  /* disable constraint */
9579  SCIP_CALL( SCIPdelCons(scip, cons) );
9580  if( !consdata->upgraded )
9581  (*ndelconss)++;
9582 
9583  return SCIP_OKAY;
9584 }
9585 
9586 /** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9587 static
9589  SCIP* scip, /**< SCIP data structure */
9590  SCIP_CONS* cons, /**< linear constraint */
9591  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9592  int* naggrvars, /**< pointer to count number of aggregated variables */
9593  int* ndelconss /**< pointer to count number of deleted constraints */
9594  )
9595 {
9596  SCIP_CONSDATA* consdata;
9597  SCIP_Bool infeasible;
9598  SCIP_Bool redundant;
9599  SCIP_Bool aggregated;
9600 
9601  assert(scip != NULL);
9602  assert(cons != NULL);
9603  assert(cutoff != NULL);
9604  assert(naggrvars != NULL);
9605  assert(ndelconss != NULL);
9606 
9607  consdata = SCIPconsGetData(cons);
9608  assert(consdata != NULL);
9609  assert(consdata->nvars == 2);
9610  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9611 
9612  SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9613  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9614  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9615 
9616  /* aggregate the equality */
9617  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9618  consdata->rhs, &infeasible, &redundant, &aggregated) );
9619 
9620  /* check for infeasibility of aggregation */
9621  if( infeasible )
9622  {
9623  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9624  *cutoff = TRUE;
9625  return SCIP_OKAY;
9626  }
9627 
9628  /* count the aggregation */
9629  if( aggregated )
9630  (*naggrvars)++;
9631 
9632  /* delete the constraint, if it is redundant */
9633  if( redundant )
9634  {
9635  SCIP_CALL( SCIPdelCons(scip, cons) );
9636 
9637  if( !consdata->upgraded )
9638  (*ndelconss)++;
9639  }
9640 
9641  return SCIP_OKAY;
9642 }
9643 
9644 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9645 static
9647  SCIP* scip, /**< SCIP data structure */
9648  SCIP_CONSDATA* consdata, /**< linear constraint data */
9649  SCIP_VAR* slackvar, /**< variable to be aggregated out */
9650  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9651  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9652  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9653  )
9654 {
9655  SCIP_Real slackvarlb;
9656  SCIP_Real slackvarub;
9657 
9658  assert(scip != NULL);
9659  assert(consdata != NULL);
9660  assert(newlhs != NULL);
9661  assert(newrhs != NULL);
9662  assert(!SCIPisInfinity(scip, -consdata->lhs));
9663  assert(!SCIPisInfinity(scip, consdata->rhs));
9664 
9665  slackvarlb = SCIPvarGetLbGlobal(slackvar);
9666  slackvarub = SCIPvarGetUbGlobal(slackvar);
9667  if( slackcoef > 0.0 )
9668  {
9669  if( SCIPisInfinity(scip, -slackvarlb) )
9670  *newrhs = SCIPinfinity(scip);
9671  else
9672  *newrhs = consdata->rhs - slackcoef * slackvarlb;
9673  if( SCIPisInfinity(scip, slackvarub) )
9674  *newlhs = -SCIPinfinity(scip);
9675  else
9676  *newlhs = consdata->lhs - slackcoef * slackvarub;
9677  }
9678  else
9679  {
9680  if( SCIPisInfinity(scip, -slackvarlb) )
9681  *newlhs = -SCIPinfinity(scip);
9682  else
9683  *newlhs = consdata->rhs - slackcoef * slackvarlb;
9684  if( SCIPisInfinity(scip, slackvarub) )
9685  *newrhs = SCIPinfinity(scip);
9686  else
9687  *newrhs = consdata->lhs - slackcoef * slackvarub;
9688  }
9689  assert(SCIPisLE(scip, *newlhs, *newrhs));
9690 }
9691 
9692 /** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9693  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9694  * is implicitly integral by this constraint
9695  *
9696  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9697  * can help.
9698  */
9699 static
9701  SCIP* scip, /**< SCIP data structure */
9702  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9703  SCIP_CONS* cons, /**< linear constraint */
9704  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9705  int* naggrvars, /**< pointer to count number of aggregated variables */
9706  int* ndelconss /**< pointer to count number of deleted constraints */
9707  )
9708 {
9709  SCIP_CONSDATA* consdata;
9710  SCIP_VAR** vars;
9711  SCIP_Real* vals;
9712  SCIP_VARTYPE bestslacktype;
9713  SCIP_VARTYPE slacktype;
9714  SCIP_Real lhs;
9715  SCIP_Real rhs;
9716  SCIP_Real bestslackdomrng;
9717  SCIP_Real minabsval;
9718  SCIP_Real maxabsval;
9719  SCIP_Bool bestremovescons;
9720  SCIP_Bool coefszeroone;
9721  SCIP_Bool coefsintegral;
9722  SCIP_Bool varsintegral;
9723  SCIP_Bool infeasible;
9724  SCIP_Bool samevar;
9725  int supinf; /* counter for infinite contributions to the supremum of a possible
9726  * multi-aggregation
9727  */
9728  int infinf; /* counter for infinite contributions to the infimum of a possible
9729  * multi-aggregation
9730  */
9731  int maxnlocksstay;
9732  int maxnlocksremove;
9733  int bestslackpos;
9734  int bestnlocks;
9735  int ncontvars;
9736  int contvarpos;
9737  int nintvars;
9738  int nimplvars;
9739  int intvarpos;
9740  int v;
9741 
9742  assert(scip != NULL);
9743  assert(cons != NULL);
9744  assert(cutoff != NULL);
9745  assert(naggrvars != NULL);
9746 
9747  consdata = SCIPconsGetData(cons);
9748  assert(consdata != NULL);
9749  assert(consdata->nvars > 2);
9750  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9751 
9752  SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9753 
9754  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9755  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9756  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9757  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9758  */
9759  lhs = consdata->lhs;
9760  rhs = consdata->rhs;
9761  maxnlocksstay = 0;
9762  if( consdata->nvars == 3 )
9763  {
9764  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9765  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9766  */
9767  maxnlocksremove = 3;
9768  }
9769  else if( consdata->nvars == 4 )
9770  {
9771  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9772  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9773  */
9774  maxnlocksremove = 2;
9775  }
9776  else
9777  {
9778  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9779  maxnlocksremove = 1;
9780  }
9781 
9782  /* the locks on this constraint can be ignored */
9783  if( SCIPconsIsChecked(cons) )
9784  {
9785  if( !SCIPisInfinity(scip, -lhs) )
9786  {
9787  maxnlocksstay++;
9788  maxnlocksremove++;
9789  }
9790  if( !SCIPisInfinity(scip, rhs) )
9791  {
9792  maxnlocksstay++;
9793  maxnlocksremove++;
9794  }
9795  }
9796 
9797  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9798  vars = consdata->vars;
9799  vals = consdata->vals;
9800  bestslackpos = -1;
9801  bestslacktype = SCIP_VARTYPE_BINARY;
9802  bestnlocks = INT_MAX;
9803  bestremovescons = FALSE;
9804  bestslackdomrng = 0.0;
9805  coefszeroone = TRUE;
9806  coefsintegral = TRUE;
9807  varsintegral = TRUE;
9808  ncontvars = 0;
9809  contvarpos = -1;
9810  nintvars = 0;
9811  nimplvars = 0;
9812  intvarpos = -1;
9813  minabsval = SCIPinfinity(scip);
9814  maxabsval = -1.0;
9815  for( v = 0; v < consdata->nvars; ++v )
9816  {
9817  SCIP_VAR* var;
9818  SCIP_Real val;
9819  SCIP_Real absval;
9820  SCIP_Real varlb;
9821  SCIP_Real varub;
9822  SCIP_Bool iscont;
9823  int nlocks;
9824 
9825  assert(vars != NULL);
9826  assert(vals != NULL);
9827 
9828  var = vars[v];
9829  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9830  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= 1);
9831  varlb = SCIPvarGetLbGlobal(var);
9832  varub = SCIPvarGetUbGlobal(var);
9833 
9834  val = vals[v];
9835  absval = REALABS(val);
9836  assert(SCIPisPositive(scip, absval));
9837 
9838  /* calculate minimal and maximal absolute value */
9839  if( absval < minabsval )
9840  minabsval = absval;
9841  if( absval > maxabsval )
9842  maxabsval = absval;
9843 
9844  /* do not try to multi aggregate, when numerical bad */
9845  if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9846  return SCIP_OKAY;
9847 
9848  slacktype = SCIPvarGetType(var);
9849  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9850  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9851  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9852  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9853 
9854  /* update candidates for continuous -> implint and integer -> implint conversion */
9855  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9856  {
9857  ncontvars++;
9858  contvarpos = v;
9859  }
9860  else if( slacktype == SCIP_VARTYPE_IMPLINT )
9861  {
9862  ++nimplvars;
9863  }
9864  else if( slacktype == SCIP_VARTYPE_INTEGER )
9865  {
9866  nintvars++;
9867  intvarpos = v;
9868  }
9869 
9870  /* check, if variable is already fixed or aggregated */
9871  if( !SCIPvarIsActive(var) )
9872  continue;
9873 
9874  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9876 
9877  if( nlocks > maxnlocksremove )
9878  continue;
9879 
9880  /* check, if variable can be used as a slack variable */
9881  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9882  !SCIPdoNotMultaggrVar(scip, var) )
9883  {
9884  SCIP_Bool better;
9885  SCIP_Bool equal;
9886  SCIP_Real slackdomrng;
9887 
9888  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9889  slackdomrng = SCIPinfinity(scip);
9890  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9891  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9892  return SCIP_OKAY;
9893  else
9894  {
9895  slackdomrng = (varub - varlb)*absval;
9896  assert(!SCIPisInfinity(scip, slackdomrng));
9897  }
9898  equal = FALSE;
9899  better = (slacktype > bestslacktype) || (bestslackpos == -1);
9900  if( !better && slacktype == bestslacktype )
9901  {
9902  better = (nlocks < bestnlocks);
9903  if( nlocks == bestnlocks && !bestremovescons )
9904  {
9905  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9906  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9907  }
9908  }
9909 
9910  if( better || equal )
9911  {
9912  SCIP_Real minresactivity;
9913  SCIP_Real maxresactivity;
9914  SCIP_Real newlhs;
9915  SCIP_Real newrhs;
9916  SCIP_Bool removescons;
9917  SCIP_Bool minisrelax;
9918  SCIP_Bool maxisrelax;
9919  SCIP_Bool isminsettoinfinity;
9920  SCIP_Bool ismaxsettoinfinity;
9921 
9922  /* check if the constraint becomes redundant after multi-aggregation */
9923  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9924  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9925 
9926  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9927  * activity
9928  */
9929  if( minisrelax || maxisrelax )
9930  continue;
9931 
9932  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9933  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9934 
9935  /* check resactivities for reliability */
9936  if( removescons )
9937  {
9938  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9939  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9940 
9941  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9942  && SCIPisFeasLE(scip, newlhs, minresactivity))
9943  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9944 
9945  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9946  }
9947 
9948  /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9949  if( conshdlrdata->multaggrremove && !removescons )
9950  continue;
9951 
9952  /* prefer variables that make the constraints redundant */
9953  if( bestremovescons && !removescons )
9954  continue;
9955 
9956  /* if the constraint does not become redundant, only accept the variable if it does not appear in
9957  * other constraints
9958  */
9959  if( !removescons && nlocks > maxnlocksstay )
9960  continue;
9961 
9962  better = better || (!bestremovescons && removescons);
9963  if( better )
9964  {
9965  bestslackpos = v;
9966  bestslacktype = slacktype;
9967  bestnlocks = nlocks;
9968  bestslackdomrng = slackdomrng;
9969  bestremovescons = removescons;
9970  }
9971  }
9972  }
9973  }
9974 
9975  /* if all coefficients and variables are integral, the right hand side must also be integral */
9976  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9977  {
9978  SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9979  SCIPdebugPrintCons(scip, cons, NULL);
9980  *cutoff = TRUE;
9981  return SCIP_OKAY;
9982  }
9983 
9984  supinf = 0;
9985  infinf = 0;
9986  samevar = FALSE;
9987 
9988  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9989  for( v = 0; v < consdata->nvars; ++v )
9990  {
9991  if( v != bestslackpos )
9992  {
9993  if( SCIPisPositive(scip, consdata->vals[v]) )
9994  {
9995  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9996  {
9997  ++supinf;
9998  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9999  {
10000  ++infinf;
10001  samevar = TRUE;
10002  }
10003  }
10004  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10005  ++infinf;
10006  }
10007  else if( SCIPisNegative(scip, consdata->vals[v]) )
10008  {
10009  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10010  {
10011  ++supinf;
10012  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10013  {
10014  ++infinf;
10015  samevar = TRUE;
10016  }
10017  }
10018  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10019  ++infinf;
10020  }
10021  }
10022  }
10023  assert(!samevar || (supinf > 0 && infinf > 0));
10024 
10025  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10026  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10027  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
10028  {
10029  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10030  return SCIP_OKAY;
10031  }
10032 
10033  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
10034  * we cannot aggregate the variable, because the integrality condition would get lost
10035  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
10036  * loose the integrality condition for this variable.
10037  */
10038  if( bestslackpos >= 0
10039  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
10040  || (coefsintegral && varsintegral && nimplvars == 0)) )
10041  {
10042  SCIP_VAR* slackvar;
10043  SCIP_Real* scalars;
10044  SCIP_Real slackcoef;
10045  SCIP_Real aggrconst;
10046  SCIP_Real newlhs;
10047  SCIP_Real newrhs;
10048  SCIP_Bool aggregated;
10049 
10050  /* we found a slack variable that only occurs in at most one other constraint:
10051  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
10052  */
10053  assert(bestslackpos < consdata->nvars);
10054 
10055  /* do not multi aggregate binary variables */
10056  if( SCIPvarIsBinary(vars[bestslackpos]) )
10057  return SCIP_OKAY;
10058 
10059  /* convert equality into inequality by deleting the slack variable:
10060  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
10061  */
10062  slackvar = vars[bestslackpos];
10063  slackcoef = vals[bestslackpos];
10064  assert(!SCIPisZero(scip, slackcoef));
10065  aggrconst = consdata->rhs/slackcoef;
10066 
10067  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
10068  assert(SCIPisLE(scip, newlhs, newrhs));
10069  SCIP_CALL( chgLhs(scip, cons, newlhs) );
10070  SCIP_CALL( chgRhs(scip, cons, newrhs) );
10071  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
10072 
10073  /* allocate temporary memory */
10074  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
10075 
10076  /* set up the multi-aggregation */
10077  SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
10078  for( v = 0; v < consdata->nvars; ++v )
10079  {
10080  scalars[v] = -consdata->vals[v]/slackcoef;
10081  SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
10082  }
10083  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
10084  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
10085  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
10086 
10087  /* perform the multi-aggregation */
10088  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10089  &infeasible, &aggregated) );
10090  assert(aggregated);
10091 
10092  /* free temporary memory */
10093  SCIPfreeBufferArray(scip, &scalars);
10094 
10095  /* check for infeasible aggregation */
10096  if( infeasible )
10097  {
10098  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10099  *cutoff = TRUE;
10100  return SCIP_OKAY;
10101  }
10102 
10103  (*naggrvars)++;
10104 
10105  /* delete the constraint if it became redundant */
10106  if( bestremovescons )
10107  {
10108  SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10109  SCIP_CALL( SCIPdelCons(scip, cons) );
10110 
10111  if( !consdata->upgraded )
10112  (*ndelconss)++;
10113  }
10114  }
10115  else if( ncontvars == 1 )
10116  {
10117  SCIP_VAR* var;
10118 
10119  assert(0 <= contvarpos && contvarpos < consdata->nvars);
10120  var = vars[contvarpos];
10121  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
10122 
10123  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10124  {
10125  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10126  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10127  {
10128  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10129  SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10130  SCIPconsGetName(cons), SCIPvarGetName(var));
10131  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10132  if( infeasible )
10133  {
10134  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10135  *cutoff = TRUE;
10136 
10137  return SCIP_OKAY;
10138  }
10139  }
10140  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10141  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10142  else if( !SCIPdoNotAggr(scip) )
10143  {
10144  SCIP_VAR* newvar;
10145  SCIP_Real absval;
10146  char newvarname[SCIP_MAXSTRLEN];
10147  SCIP_Bool redundant;
10148  SCIP_Bool aggregated;
10149 
10150  absval = REALABS(vals[contvarpos]);
10151 
10152  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10153 
10154  /* create new implicit variable for aggregation */
10155  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10157 
10158  /* add new variable to problem */
10159  SCIP_CALL( SCIPaddVar(scip, newvar) );
10160 
10161 #ifdef WITH_DEBUG_SOLUTION
10162  if( SCIPdebugIsMainscip(scip) )
10163  {
10164  SCIP_Real varval;
10165  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10166  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10167  }
10168 #endif
10169 
10170  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10171  SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10172  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10173 
10174  /* aggregate continuous and implicit variable */
10175  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10176 
10177  if( infeasible )
10178  {
10179  SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10180  SCIPvarGetName(var), SCIPvarGetName(newvar));
10181  *cutoff = TRUE;
10182 
10183  /* release implicit variable */
10184  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10185 
10186  return SCIP_OKAY;
10187  }
10188 
10189  /* release implicit variable */
10190  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10191 
10192  if( aggregated )
10193  (*naggrvars)++;
10194  else
10195  return SCIP_OKAY;
10196  }
10197 
10198  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10199  * again
10200  */
10201  consdata->boundstightened = 0;
10202  consdata->rangedrowpropagated = 0;
10203  consdata->presolved = FALSE;
10204  }
10205  }
10206  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10207  {
10208  SCIP_VAR* var;
10209 
10210  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10211  * -> we don't convert integers into implints if the row is a 0/1-row
10212  */
10213  assert(varsintegral);
10214  assert(0 <= intvarpos && intvarpos < consdata->nvars);
10215  var = vars[intvarpos];
10216  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10217 
10218  if( coefsintegral
10219  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10220  && SCIPisFeasIntegral(scip, consdata->rhs) )
10221  {
10222  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10223  SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10224  SCIPconsGetName(cons), SCIPvarGetName(var));
10225  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10226  if( infeasible )
10227  {
10228  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10229  *cutoff = TRUE;
10230 
10231  return SCIP_OKAY;
10232  }
10233  }
10234  }
10235 
10236  return SCIP_OKAY;
10237 }
10238 
10239 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10240 static
10242  SCIP* scip, /**< SCIP data structure */
10243  SCIP_CONSDATA* consdata, /**< linear constraint data */
10244  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10245  * objective function */
10246  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10247  * this constraint */
10248  )
10249 {
10250  SCIP_VAR** vars;
10251  SCIP_VAR* var;
10252  SCIP_Real objval;
10253  SCIP_Bool negated;
10254  int nvars;
10255  int v;
10256 
10257  vars = consdata->vars;
10258  nvars = consdata->nvars;
10259 
10260  assert(vars != NULL);
10261 
10262  for( v = 0; v < nvars; ++v )
10263  {
10264  negated = FALSE;
10265  var = vars[v];
10266  assert(var != NULL);
10267 
10268  if( SCIPvarIsNegated(var) )
10269  {
10270  negated = TRUE;
10271  var = SCIPvarGetNegatedVar(var);
10272  assert(var != NULL);
10273  }
10274 
10275  objval = SCIPvarGetObj(var);
10276 
10277  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10278  * function
10279  */
10280  if( SCIPisZero(scip, objval) )
10281  return FALSE;
10282  else
10283  {
10284  SCIP_Real val;
10285 
10286  val = consdata->vals[v];
10287 
10288  if( negated )
10289  {
10290  if( v == 0 )
10291  {
10292  /* the first variable defines the scale */
10293  (*scale) = val / -objval;
10294 
10295  (*offset) += val;
10296  }
10297  else if( SCIPisEQ(scip, -objval * (*scale), val) )
10298  (*offset) += val;
10299  else
10300  return FALSE;
10301  }
10302  else if( v == 0 )
10303  {
10304  /* the first variable defines the scale */
10305  (*scale) = val / objval;
10306  }
10307  else if( !SCIPisEQ(scip, objval * (*scale), val) )
10308  return FALSE;
10309  }
10310  }
10311 
10312  return TRUE;
10313 }
10314 
10315 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10316  * objective coefficients and add an objective offset
10317  */
10318 static
10320  SCIP* scip, /**< SCIP data structure */
10321  SCIP_CONS* cons, /**< linear equation constraint */
10322  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10323  )
10324 {
10325  SCIP_CONSDATA* consdata;
10326  SCIP_Real offset;
10327  SCIP_Real scale;
10328  SCIP_Bool applicable;
10329  int nobjvars;
10330  int nvars;
10331  int v;
10332 
10333  assert(scip != NULL);
10334  assert(cons != NULL);
10335  assert(conshdlrdata != NULL);
10336 
10337  consdata = SCIPconsGetData(cons);
10338  assert(consdata != NULL);
10339  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10340 
10341  nvars = consdata->nvars;
10342  nobjvars = SCIPgetNObjVars(scip);
10343 
10344  /* check if the linear equality constraints does not have more variables than the objective function */
10345  if( nvars > nobjvars || nvars == 0 )
10346  return SCIP_OKAY;
10347 
10348  /* check for allowance of algorithm */
10349  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10350  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10351  return SCIP_OKAY;
10352 
10353  offset = consdata->rhs;
10354  scale = 1.0;
10355 
10356  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10357  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10358 
10359  if( applicable )
10360  {
10361  SCIP_VAR** vars;
10362 
10363  vars = consdata->vars;
10364  assert(vars != NULL);
10365 
10366  offset /= scale;
10367 
10368  SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10369  SCIPconsGetName(cons), consdata->rhs, offset);
10370 
10371  /* make equality a model constraint to ensure optimality in this direction */
10372  SCIP_CALL( SCIPsetConsChecked(scip, cons, TRUE) );
10373  SCIP_CALL( SCIPsetConsEnforced(scip, cons, TRUE) );
10374 
10375  /* set all objective coefficient to zero */
10376  for( v = 0; v < nvars; ++v )
10377  {
10378  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10379  }
10380 
10381  /* add an objective offset */
10382  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10383  }
10384 
10385  return SCIP_OKAY;
10386 }
10387 
10388 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10389 static
10391  SCIP* scip, /**< SCIP data structure */
10392  SCIP_CONS* cons, /**< constraint */
10393  SCIP_Real primalbound /**< feasible primal bound */
10394  )
10395 {
10396  SCIP_Real cutoffbound;
10397 
10398  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10399  * accepted
10400  */
10401  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10402 
10403  if( cutoffbound < SCIPgetCutoffbound(scip) )
10404  {
10405  SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10406 
10407  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10408  }
10409  else
10410  {
10411  SCIP_CONSDATA* consdata;
10412 
10413  consdata = SCIPconsGetData(cons);
10414  assert(consdata != NULL);
10415 
10416  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10417  * resulted from one side
10418  */
10419  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10420  {
10421  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10422  * propagation
10423  */
10424  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
10425  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
10426  }
10427  }
10428 
10429  return SCIP_OKAY;
10430 }
10431 
10432 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10433  * constraint enters the LP by setting the initial and separated flag to FALSE
10434  */
10435 static
10437  SCIP* scip, /**< SCIP data structure */
10438  SCIP_CONS* cons, /**< linear constraint */
10439  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10440  )
10441 {
10442  SCIP_CONSDATA* consdata;
10443  SCIP_Real offset;
10444  SCIP_Real scale;
10445  SCIP_Bool applicable;
10446  int nobjvars;
10447  int nvars;
10448 
10449  assert(scip != NULL);
10450  assert(cons != NULL);
10451  assert(conshdlrdata != NULL);
10452 
10453  consdata = SCIPconsGetData(cons);
10454  assert(consdata != NULL);
10456  /* ignore equalities since these are covered by the method checkPartialObjective() */
10457  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10458  return SCIP_OKAY;
10459 
10460  nvars = consdata->nvars;
10461  nobjvars = SCIPgetNObjVars(scip);
10462 
10463  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10464  * initial and/or separated flag is set to FALSE
10465  */
10466  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10467  return SCIP_OKAY;
10468 
10469  offset = 0.0;
10470  scale = 1.0;
10471 
10472  /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10473  * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10474  */
10475  if( nobjvars == 0 )
10476  return SCIP_OKAY;
10477 
10478  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10479  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10480 
10481  if( applicable )
10482  {
10483  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10484  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10485 
10486  assert(scale != 0.0);
10487 
10488  if( scale > 0.0 )
10489  {
10490  if( conshdlrdata->detectcutoffbound && rhsfinite )
10491  {
10492  SCIP_Real primalbound;
10493 
10494  primalbound = (consdata->rhs - offset) / scale;
10495 
10496  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10497  SCIPconsGetName(cons), primalbound);
10498 
10499  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10500  }
10501 
10502  if( conshdlrdata->detectlowerbound && lhsfinite )
10503  {
10504  SCIP_Real lowerbound;
10505 
10506  lowerbound = (consdata->lhs - offset) / scale;
10507 
10508  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10509  SCIPconsGetName(cons), lowerbound);
10510 
10511  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10512  }
10513 
10514  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10515  (conshdlrdata->detectlowerbound && !rhsfinite) )
10516  {
10517  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10518  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10519  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10520  }
10521  }
10522  else
10523  {
10524  if( conshdlrdata->detectlowerbound && rhsfinite )
10525  {
10526  SCIP_Real lowerbound;
10527 
10528  lowerbound = (consdata->rhs - offset) / scale;
10529 
10530  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10531  SCIPconsGetName(cons), lowerbound);
10532 
10533  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10534  }
10535 
10536  if( conshdlrdata->detectcutoffbound && lhsfinite )
10537  {
10538  SCIP_Real primalbound;
10539 
10540  primalbound = (consdata->lhs - offset) / scale;
10541 
10542  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10543  SCIPconsGetName(cons), primalbound);
10544 
10545  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10546  }
10547 
10548  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10549  (conshdlrdata->detectlowerbound && !lhsfinite) )
10550  {
10551  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10552  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10553  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10554  }
10555  }
10556  }
10557 
10558  return SCIP_OKAY;
10559 }
10560 
10561 /** converts special equalities */
10562 static
10564  SCIP* scip, /**< SCIP data structure */
10565  SCIP_CONS* cons, /**< linear constraint */
10566  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10567  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10568  int* nfixedvars, /**< pointer to count number of fixed variables */
10569  int* naggrvars, /**< pointer to count number of aggregated variables */
10570  int* ndelconss /**< pointer to count number of deleted constraints */
10571  )
10572 {
10573  SCIP_CONSDATA* consdata;
10574 
10575  assert(scip != NULL);
10576  assert(cons != NULL);
10577  assert(conshdlrdata != NULL);
10578  assert(cutoff != NULL);
10579  assert(nfixedvars != NULL);
10580  assert(naggrvars != NULL);
10581  assert(ndelconss != NULL);
10583  consdata = SCIPconsGetData(cons);
10584  assert(consdata != NULL);
10585  assert(consdata->removedfixings);
10586 
10587  /* do nothing on inequalities */
10588  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10589  return SCIP_OKAY;
10590 
10591  /* depending on the number of variables, call a special conversion method */
10592  if( consdata->nvars == 1 )
10593  {
10594  /* fix variable */
10595  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10596  }
10597  else if( consdata->nvars == 2 )
10598  {
10599  /* aggregate one of the variables */
10600  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10601  }
10602  else
10603  {
10604  /* check if the equality is part of the objective function */
10605  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10606 
10607  /* try to multi-aggregate one of the variables */
10608  SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10609  }
10610 
10611  return SCIP_OKAY;
10612 }
10613 
10614 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10615  * integral
10616  */
10617 static
10619  SCIP* scip, /**< SCIP data structure */
10620  SCIP_CONSDATA* consdata, /**< linear constraint */
10621  int pos, /**< position of variable to be left out */
10622  SCIP_Real val /**< value to divide the coefficients by */
10623  )
10624 {
10625  int v;
10626 
10627  assert(scip != NULL);
10628  assert(consdata != NULL);
10629  assert(0 <= pos && pos < consdata->nvars);
10630 
10631  for( v = 0; v < consdata->nvars; ++v )
10632  {
10633  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10634  return FALSE;
10635  }
10636 
10637  return TRUE;
10638 }
10639 
10640 /** 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$,
10641  * 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$
10642  */
10643 static
10645  SCIP* scip, /**< SCIP data structure */
10646  SCIP_Real side, /**< lhs or rhs */
10647  SCIP_Real val, /**< coefficient */
10648  SCIP_Real minresactivity, /**< minimal residual activity */
10649  SCIP_Real maxresactivity, /**< maximal residual activity */
10650  SCIP_Real* minval, /**< pointer to store calculated minval */
10651  SCIP_Real* maxval /**< pointer to store calculated maxval */
10652  )
10653 {
10654  assert(scip != NULL);
10655  assert(minval != NULL);
10656  assert(maxval != NULL);
10657 
10658  if( val > 0.0 )
10659  {
10660  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10661  *minval = -maxresactivity;
10662  else
10663  *minval = (side - maxresactivity)/val;
10664 
10665  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10666  *maxval = -minresactivity;
10667  else
10668  *maxval = (side - minresactivity)/val;
10669  }
10670  else
10671  {
10672  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10673  *minval = minresactivity;
10674  else
10675  *minval = (side - minresactivity)/val;
10676 
10677  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10678  *maxval = maxresactivity;
10679  else
10680  *maxval = (side - maxresactivity)/val;
10681  }
10682 }
10683 
10684 
10685 /** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10686  * linear inequality
10687  */
10688 static
10690  SCIP* scip, /**< SCIP data structure */
10691  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10692  SCIP_CONS* cons, /**< linear constraint */
10693  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10694  int* nfixedvars, /**< pointer to count number of fixed variables */
10695  int* naggrvars, /**< pointer to count number of aggregated variables */
10696  int* ndelconss /**< pointer to count number of deleted constraints */
10697  )
10698 {
10699  SCIP_CONSDATA* consdata;
10700  SCIP_Bool lhsexists;
10701  SCIP_Bool rhsexists;
10702  SCIP_Bool bestisint;
10703  SCIP_Bool bestislhs;
10704  SCIP_Real minabsval;
10705  SCIP_Real maxabsval;
10706  int bestpos;
10707  int i;
10708  int maxotherlocks;
10709 
10710  assert(scip != NULL);
10711  assert(cons != NULL);
10712  assert(cutoff != NULL);
10713  assert(nfixedvars != NULL);
10714  assert(naggrvars != NULL);
10715  assert(ndelconss != NULL);
10716 
10717  /* only process checked constraints (for which the locks are increased);
10718  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10719  * dualfix presolver
10720  */
10721  if( !SCIPconsIsChecked(cons) )
10722  return SCIP_OKAY;
10723 
10724  consdata = SCIPconsGetData(cons);
10725  assert(consdata != NULL);
10726 
10727  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10728  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10729 
10730  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10731  * can use it safely for aggregation and break the search loop
10732  */
10733  bestpos = -1;
10734  bestisint = TRUE;
10735  bestislhs = FALSE;
10736 
10737  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10738  * everything else would produce fill-in. Exceptions:
10739  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10740  * produced.
10741  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10742  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10743  * six nonzeros (two variables per substitution).
10744  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10745  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10746  * six nonzeros (three variables per substitution). God exists!
10747  */
10748  if( consdata->nvars <= 2 )
10749  maxotherlocks = INT_MAX;
10750  else if( consdata->nvars == 3 )
10751  maxotherlocks = 3;
10752  else if( consdata->nvars == 4 )
10753  maxotherlocks = 2;
10754  else
10755  maxotherlocks = 1;
10756 
10757  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10758  if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10759  maxotherlocks++;
10760 
10761  minabsval = SCIPinfinity(scip);
10762  maxabsval = -1.0;
10763  for( i = 0; i < consdata->nvars && bestisint; ++i )
10764  {
10765  SCIP_VAR* var;
10766  SCIP_Bool isint;
10767  SCIP_Real val;
10768  SCIP_Real absval;
10769  SCIP_Real obj;
10770  SCIP_Real lb;
10771  SCIP_Real ub;
10772  SCIP_Bool agglhs;
10773  SCIP_Bool aggrhs;
10774 
10775  val = consdata->vals[i];
10776  absval = REALABS(val);
10777 
10778  /* calculate minimal and maximal absolute value */
10779  if( absval < minabsval )
10780  minabsval = absval;
10781  if( absval > maxabsval )
10782  maxabsval = absval;
10783 
10784  /* do not try to multi aggregate, when numerical bad */
10785  if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10786  return SCIP_OKAY;
10787 
10788  var = consdata->vars[i];
10790 
10791  /* if we already found a candidate, skip integers */
10792  if( bestpos >= 0 && isint )
10793  continue;
10794 
10795  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10796  * active, fixed, or single-aggregated with another binary variable
10797  */
10798  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10799  continue;
10800 
10801  if ( SCIPdoNotMultaggrVar(scip, var) )
10802  continue;
10803 
10804  val = consdata->vals[i];
10805  obj = SCIPvarGetObj(var);
10806  lb = SCIPvarGetLbGlobal(var);
10807  ub = SCIPvarGetUbGlobal(var);
10808 
10809  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10810  *
10811  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10812  * - constraint is the only one that forbids fixing the variable to its lower bound
10813  * - 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
10814  *
10815  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10816  * - constraint is the only one that forbids fixing the variable to its upper bound
10817  * - 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
10818  *
10819  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10820  * - constraint is the only one that forbids fixing the variable to its upper bound
10821  * - 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
10822  *
10823  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10824  * - constraint is the only one that forbids fixing the variable to its lower bound
10825  * - 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
10826  *
10827  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10828  * of all x_j
10829  * furthermore: we only want to apply this, if no fill-in will be produced
10830  */
10831  agglhs = lhsexists
10832  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10833  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10834  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10835  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10836  aggrhs = rhsexists
10837  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10838  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10839  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10840  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10841  if( agglhs || aggrhs )
10842  {
10843  SCIP_Real minresactivity;
10844  SCIP_Real maxresactivity;
10845  SCIP_Real minval;
10846  SCIP_Real maxval;
10847  SCIP_Bool minisrelax;
10848  SCIP_Bool maxisrelax;
10849  SCIP_Bool isminsettoinfinity;
10850  SCIP_Bool ismaxsettoinfinity;
10851 
10852  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10853  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10854  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
10855  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10856 
10857  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10858  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10859  * This is needed, because we do not want to rely on relaxed finite resactivities.
10860  */
10861  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
10862 
10863  if( agglhs )
10864  {
10865  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10866  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10867 
10868  assert(SCIPisLE(scip, minval, maxval));
10869  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10870  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10871  {
10872  SCIP_Real oldmaxresactivity;
10873  SCIP_Real oldminresactivity;
10874  SCIP_Bool recalculated;
10875 
10876  recalculated = FALSE;
10877  oldmaxresactivity = maxresactivity;
10878  oldminresactivity = minresactivity;
10879 
10880  /* check minresactivity for reliability */
10881  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10882  {
10883  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10884  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10885  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10886  }
10887 
10888  /* check maxresactivity for reliability */
10889  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10890  {
10891  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10892  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10893  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10894  }
10895 
10896  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10897  if( recalculated )
10898  {
10899  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10900 
10901  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10902  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10903 
10904  assert(SCIPisLE(scip, minval, maxval));
10905  }
10906 
10907  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10908  {
10909  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10910  * in the multi-aggregation
10911  */
10912  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10913  {
10914  bestpos = i;
10915  bestisint = isint;
10916  bestislhs = TRUE;
10917  continue; /* no need to also look at the right hand side */
10918  }
10919  }
10920  }
10921  }
10922 
10923  if( aggrhs )
10924  {
10925  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10926  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10927 
10928  assert(SCIPisLE(scip,minval,maxval));
10929  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10930  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10931  {
10932  SCIP_Real oldmaxresactivity;
10933  SCIP_Real oldminresactivity;
10934  SCIP_Bool recalculated;
10935 
10936  recalculated = FALSE;
10937  oldmaxresactivity = maxresactivity;
10938  oldminresactivity = minresactivity;
10939 
10940  /* check minresactivity for reliability */
10941  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10942  {
10943  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10944  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10945  }
10946 
10947  /* check maxresactivity for reliability */
10948  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10949  {
10950  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10951  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10952  }
10953 
10954  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10955  if( recalculated )
10956  {
10957  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10958  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10959  assert(SCIPisLE(scip,minval,maxval));
10960  }
10961 
10962  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10963  {
10964  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10965  * in the multi-aggregation
10966  */
10967  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10968  {
10969  bestpos = i;
10970  bestisint = isint;
10971  bestislhs = FALSE;
10972  }
10973  }
10974  }
10975  }
10976  }
10977  }
10978 
10979  if( bestpos >= 0 )
10980  {
10981  SCIP_VAR** aggrvars;
10982  SCIP_Real* aggrcoefs;
10983  SCIP_Real aggrconst;
10984  SCIP_VAR* bestvar;
10985  SCIP_Real bestval;
10986  SCIP_Real epsilon;
10987  int naggrs;
10988  int j;
10989  SCIP_Bool infeasible;
10990  SCIP_Bool aggregated;
10991  SCIP_Bool samevar;
10992  int supinf; /* counter for infinite contributions to the supremum of a possible
10993  * multi-aggregation
10994  */
10995  int infinf; /* counter for infinite contributions to the infimum of a possible
10996  * multi-aggregation
10997  */
10998 
10999  assert(!bestislhs || lhsexists);
11000  assert(bestislhs || rhsexists);
11001 
11002  bestvar = consdata->vars[bestpos];
11003  bestval = consdata->vals[bestpos];
11004  assert(bestisint ==
11006 
11007  /* allocate temporary memory */
11008  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
11009  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
11010 
11011  /* set up the multi-aggregation */
11012  SCIPdebugPrintCons(scip, cons, NULL);
11013  SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
11014  naggrs = 0;
11015  supinf = 0;
11016  infinf = 0;
11017  samevar = FALSE;
11018  epsilon = SCIPepsilon(scip);
11019 
11020  for( j = 0; j < consdata->nvars; ++j )
11021  {
11022  if( j != bestpos )
11023  {
11024  SCIP_Real absaggrcoef;
11025 
11026  aggrvars[naggrs] = consdata->vars[j];
11027  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
11028  SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
11029 
11030  absaggrcoef = REALABS(aggrcoefs[naggrs]);
11031 
11032  /* do not try to multi aggregate, when numerical bad */
11033  if( absaggrcoef < epsilon )
11034  {
11035  SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
11036 
11037  /* free temporary memory */
11038  SCIPfreeBufferArray(scip, &aggrcoefs);
11039  SCIPfreeBufferArray(scip, &aggrvars);
11040 
11041  return SCIP_OKAY;
11042  }
11043 
11044  if( bestisint )
11045  {
11046  /* coefficient must be integral: round it to exact integral value */
11047  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
11048  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
11049  }
11050 
11051  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
11052  {
11053  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11054  {
11055  ++supinf;
11056  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11057  {
11058  ++infinf;
11059  samevar = TRUE;
11060  }
11061  }
11062  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11063  ++infinf;
11064  }
11065  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
11066  {
11067  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11068  {
11069  ++supinf;
11070  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11071  {
11072  ++infinf;
11073  samevar = TRUE;
11074  }
11075  }
11076  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11077  ++infinf;
11078  }
11079 
11080  naggrs++;
11081  }
11082  }
11083  assert(!samevar || (supinf > 0 && infinf > 0));
11084 
11085  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11086  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11087  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
11088  assert(naggrs == consdata->nvars-1);
11089 
11090  /* right hand side must be integral: round it to exact integral value */
11091  if( bestisint )
11092  {
11093  assert(SCIPisIntegral(scip, aggrconst));
11094  aggrconst = SCIPfloor(scip, aggrconst+0.5);
11095  }
11096 
11097  aggregated = FALSE;
11098  infeasible = FALSE;
11099 
11100  /* perform the multi-aggregation */
11101  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11102  {
11103  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11104  * also convertLongEquality() early termination due to coefficients
11105  */
11106  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11107 
11108  /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11109  * the implicitness might rely on the constraint and the integrality of bestvar
11110  */
11111  if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11112  {
11113  SCIP_Bool infeasiblevartypechg;
11114 
11115  for( j = 0; j < naggrs; ++j)
11116  {
11117  /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11118  * lead to infeasibility
11119  */
11120  if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT )
11121  {
11122  SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
11123  assert(!infeasiblevartypechg);
11124  }
11125  }
11126  }
11127  }
11128  else
11129  {
11130  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11131  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11132  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11133  }
11134  /* free temporary memory */
11135  SCIPfreeBufferArray(scip, &aggrcoefs);
11136  SCIPfreeBufferArray(scip, &aggrvars);
11137 
11138  /* check for infeasible aggregation */
11139  if( infeasible )
11140  {
11141  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11142  *cutoff = TRUE;
11143  return SCIP_OKAY;
11144  }
11145 
11146  /* delete the constraint, if the aggregation was successful */
11147  if( aggregated )
11148  {
11149  SCIP_CALL( SCIPdelCons(scip, cons) );
11150 
11151  if( !consdata->upgraded )
11152  (*ndelconss)++;
11153  (*naggrvars)++;
11154  }
11155  else
11156  {
11157  SCIPdebugMsg(scip, "aggregation non successful!\n");
11158  }
11159  }
11160 
11161  return SCIP_OKAY;
11162 }
11163 
11164 #define BINWEIGHT 1
11165 #define INTWEIGHT 4
11166 #define CONTWEIGHT 8
11167 
11168 /** gets weight for variable in a "weighted number of variables" sum */
11169 static
11170 int getVarWeight(
11171  SCIP_VAR* var /**< variable to get weight for */
11172  )
11173 {
11174  switch( SCIPvarGetType(var) )
11175  {
11176  case SCIP_VARTYPE_BINARY:
11177  return BINWEIGHT;
11178  case SCIP_VARTYPE_INTEGER:
11179  case SCIP_VARTYPE_IMPLINT:
11180  return INTWEIGHT;
11182  return CONTWEIGHT;
11183  default:
11184  SCIPerrorMessage("invalid variable type\n");
11186  return 0; /*lint !e527*/
11187  }
11188 }
11190 /** tries to aggregate variables in equations a^Tx = lhs
11191  * in case there are at most two binary variables with an odd coefficient and all other
11192  * variables are not continuous and have an even coefficient then:
11193  * - exactly one odd binary variables
11194  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11195  * - lhs is odd -> y = 1
11196  * - lhs is even -> y = 0
11197  * - exactly two odd binary variables
11198  * aggregate the two binary variables with odd coefficient
11199  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11200  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11201  */
11202 static
11204  SCIP* scip, /**< SCIP data structure */
11205  SCIP_CONS* cons, /**< linear constraint */
11206  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11207  int* nfixedvars, /**< pointer to count number of fixed variables */
11208  int* naggrvars /**< pointer to count number of aggregated variables */
11209  )
11210 { /*lint --e{715}*/
11211  SCIP_CONSDATA* consdata;
11212  SCIP_Bool success;
11213 
11214  assert( scip != NULL );
11215  assert( cons != NULL );
11216 
11217  consdata = SCIPconsGetData(cons);
11218  assert( consdata != NULL );
11219 
11220  /* check if the linear constraint is an equation with integral right hand side */
11221  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11222  return SCIP_OKAY;
11223 
11224  /* try to fix and aggregated variables until nothing is possible anymore */
11225  do
11226  {
11227  int v;
11228  int nvars;
11229  SCIP_VAR** vars;
11230  SCIP_Real* vals;
11231  SCIP_Real lhs;
11232  SCIP_Bool lhsodd;
11233 
11234  SCIP_Bool infeasible;
11235  SCIP_Bool fixed;
11236  SCIP_Bool aggregated;
11237  SCIP_Bool redundant;
11238 
11239  SCIP_VAR* var1;
11240  SCIP_VAR* var2;
11241  int noddvars;
11242 
11243  success = FALSE;
11244 
11245  lhs = consdata->lhs;
11246  vars = consdata->vars;
11247  vals = consdata->vals;
11248  nvars = consdata->nvars;
11249 
11250  assert( !SCIPisInfinity(scip, ABS(lhs)) );
11251 
11252  var1 = NULL;
11253  var2 = NULL;
11254  noddvars = 0;
11255 
11256  /* search for binary variables with an odd coefficient */
11257  for( v = 0; v < nvars && noddvars < 3; ++v )
11258  {
11259  SCIP_Longint val;
11260 
11261  /* all coefficients and variables have to be integral */
11262  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11263  return SCIP_OKAY;
11264 
11265  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11266  if( val % 2 != 0 )
11267  {
11268  /* the odd values have to belong to binary variables */
11269  if( !SCIPvarIsBinary(vars[v]) )
11270  return SCIP_OKAY;
11271 
11272  if( noddvars == 0 )
11273  var1 = vars[v];
11274  else
11275  var2 = vars[v];
11276 
11277  noddvars++;
11278  }
11279  }
11280 
11281  /* check lhs is odd or even */
11282  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11283 
11284  if( noddvars == 1 )
11285  {
11286  assert( var1 != NULL );
11287 
11288  SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11289  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11290 
11291  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11292 
11293  /* check for infeasibility of fixing */
11294  if( infeasible )
11295  {
11296  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11297  *cutoff = TRUE;
11298  return SCIP_OKAY;
11299  }
11300 
11301  if( fixed )
11302  {
11303  SCIPdebugMsg(scip, " -> feasible fixing\n");
11304  (*nfixedvars)++;
11305  success = TRUE;
11306  }
11307  }
11308  else if( noddvars == 2 )
11309  {
11310  assert( var1 != NULL );
11311  assert( var2 != NULL );
11312 
11313  /* aggregate the two variables with odd coefficient
11314  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11315  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11316  */
11317  SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11318  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11319 
11320  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11321  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11322 
11323  /* check for infeasibility of aggregation */
11324  if( infeasible )
11325  {
11326  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11327  *cutoff = TRUE;
11328  return SCIP_OKAY;
11329  }
11330 
11331  /* count the aggregation */
11332  if( aggregated )
11333  {
11334  SCIPdebugMsg(scip, " -> feasible aggregation\n");
11335  (*naggrvars)++;
11336  success = TRUE;
11337  }
11338  }
11339 
11340  if( success )
11341  {
11342  /* apply fixings and aggregation to successfully rerun this presolving step */
11343  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11344 
11345  if( infeasible )
11346  {
11347  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11348  *cutoff = TRUE;
11349  return SCIP_OKAY;
11350  }
11351 
11352  /* normalize constraint */
11353  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11354 
11355  if( infeasible )
11356  {
11357  SCIPdebugMsg(scip, " -> infeasible normalization\n");
11358  *cutoff = TRUE;
11359  return SCIP_OKAY;
11360  }
11361  }
11362  }
11363  while( success );
11364 
11365  return SCIP_OKAY;
11366 }
11367 
11368 
11369 
11370 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11371  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11372  * coefficients
11373  */
11374 static
11375 SCIP_DECL_SORTINDCOMP(consdataCompSim)
11376 { /*lint --e{715}*/
11377  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11378  SCIP_VARTYPE vartype1;
11379  SCIP_VARTYPE vartype2;
11380  SCIP_Real value;
11381 
11382  assert(consdata != NULL);
11383  assert(0 <= ind1 && ind1 < consdata->nvars);
11384  assert(0 <= ind2 && ind2 < consdata->nvars);
11385 
11386  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11387  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11388 
11389  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11390  {
11391  /* continuous varibles will be sorted to the back */
11392  if( vartype2 != vartype1 )
11393  return +1;
11394  /* both variables are continuous */
11395  else
11396  return 0;
11397  }
11398  /* continuous variables will be sorted to the back */
11399  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11400  return -1;
11401 
11402  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11403 
11404  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11405  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11406 }
11407 
11408 /** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11409  *
11410  * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11411  * then we can change this constraint to 1^Tx = 1
11412  */
11413 static
11415  SCIP* scip, /**< SCIP data structure */
11416  SCIP_CONS* cons, /**< linear constraint */
11417  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11418  int* nchgsides /**< pointer to store the amount of changed sides */
11419  )
11420 {
11421  SCIP_CONSDATA* consdata;
11422  SCIP_VAR** vars;
11423  SCIP_Real* vals;
11424  SCIP_Real minval;
11425  SCIP_Real secondminval;
11426  SCIP_Real maxval;
11427  SCIP_Real lhs;
11428  SCIP_Real rhs;
11429  int nvars;
11430  int v;
11431 
11432  /* we must not change a modifiable constraint in any way */
11434  return SCIP_OKAY;
11435 
11436  if( SCIPconsIsDeleted(cons) )
11437  return SCIP_OKAY;
11438 
11439  consdata = SCIPconsGetData(cons);
11440  assert(consdata != NULL);
11441 
11442  nvars = consdata->nvars;
11443 
11444  /* do not check empty or bound-constraints */
11445  if( nvars < 2 )
11446  return SCIP_OKAY;
11447 
11448  lhs = consdata->lhs;
11449  rhs = consdata->rhs;
11450  assert(!SCIPisInfinity(scip, -lhs));
11451  assert(!SCIPisInfinity(scip, rhs));
11452  assert(!SCIPisNegative(scip, rhs));
11453 
11454  /* sides must be positive and different to detect set partition */
11455  if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11456  return SCIP_OKAY;
11457 
11458  vals = consdata->vals;
11459  vars = consdata->vars;
11460  assert(vars != NULL);
11461  assert(vals != NULL);
11462 
11463  minval = SCIP_INVALID;
11464  secondminval = SCIP_INVALID;
11465  maxval = -SCIP_INVALID;
11466 
11467  for( v = nvars - 1; v >= 0; --v )
11468  {
11469  if( SCIPvarIsBinary(vars[v]) )
11470  {
11471  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11472  {
11473  secondminval = minval;
11474  minval = vals[v];
11475  }
11476  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11477  secondminval = vals[v];
11478 
11479  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11480  maxval = vals[v];
11481  }
11482  else
11483  break;
11484  }
11485 
11486  /* check if all variables are binary, we can choose one, and need to choose at most one */
11487  if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11488  && SCIPisGT(scip, minval + secondminval, rhs) )
11489  {
11490  /* change all coefficients to 1.0 */
11491  for( v = nvars - 1; v >= 0; --v )
11492  {
11493  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11494  }
11495  (*nchgcoefs) += nvars;
11496 
11497  /* replace old right and left hand side with 1.0 */
11498  SCIP_CALL( chgRhs(scip, cons, 1.0) );
11499  SCIP_CALL( chgLhs(scip, cons, 1.0) );
11500  (*nchgsides) += 2;
11501  }
11502 
11503  return SCIP_OKAY;
11504 }
11505 
11506 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11507  *
11508  * for both-sided constraints only @see rangedRowSimplify() will be called
11509  *
11510  * for one-sided constraints there are several different coefficient reduction steps which will be applied
11511  *
11512  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11513  *
11514  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11515  *
11516  * 2. We try to remove redundant fractional parts in a constraint
11517  *
11518  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11519  *
11520  * 3. We are using the greatest common divisor for further reductions
11521  *
11522  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11523  * integral
11524  */
11525 static
11527  SCIP* scip, /**< SCIP data structure */
11528  SCIP_CONS* cons, /**< linear constraint */
11529  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11530  int* nchgsides, /**< pointer to store the amount of changed sides */
11531  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11532  )
11533 {
11534  SCIP_CONSDATA* consdata;
11535  SCIP_VAR** vars;
11536  SCIP_Real* vals;
11537  int* perm;
11538  SCIP_Real minactsub;
11539  SCIP_Real maxactsub;
11540  SCIP_Real siderest;
11541  SCIP_Real feastol;
11542  SCIP_Real newcoef;
11543  SCIP_Real absval;
11544  SCIP_Real minact;
11545  SCIP_Real maxact;
11546  SCIP_Real side;
11547  SCIP_Real lhs;
11548  SCIP_Real rhs;
11549  SCIP_Real lb;
11550  SCIP_Real ub;
11551  SCIP_Longint restcoef;
11552  SCIP_Longint oldgcd;
11553  SCIP_Longint rest;
11554  SCIP_Longint gcd;
11555  SCIP_Bool isminsettoinfinity;
11556  SCIP_Bool ismaxsettoinfinity;
11557  SCIP_Bool isminrelax;
11558  SCIP_Bool ismaxrelax;
11559  SCIP_Bool allcoefintegral;
11560  SCIP_Bool onlybin;
11561  SCIP_Bool hasrhs;
11562  SCIP_Bool haslhs;
11563  int oldnchgcoefs;
11564  int oldnchgsides;
11565  int foundbin;
11566  int candpos;
11567  int candpos2;
11568  int offsetv;
11569  int nvars;
11570  int v;
11571  int w;
11572 
11573  assert(scip != NULL);
11574  assert(cons != NULL);
11575  assert(nchgcoefs != NULL);
11576  assert(nchgsides != NULL);
11577 
11578  *infeasible = FALSE;
11579 
11580  /* we must not change a modifiable constraint in any way */
11581  if( SCIPconsIsModifiable(cons) )
11582  return SCIP_OKAY;
11583 
11584  if( SCIPconsIsDeleted(cons) )
11585  return SCIP_OKAY;
11586 
11587  consdata = SCIPconsGetData(cons);
11588  assert(consdata != NULL);
11589 
11590  nvars = consdata->nvars;
11591 
11592  /* do not check empty or bound-constraints */
11593  if( nvars <= 2 )
11594  return SCIP_OKAY;
11595 
11596  /* update maximal activity delta if necessary */
11597  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11598  consdataRecomputeMaxActivityDelta(scip, consdata);
11599 
11600  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11601  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11602  checkMaxActivityDelta(scip, consdata);
11603 
11604  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11605  * accordingly
11606  */
11607  /* can only work with valid non-infinity activities per variable */
11608  if( SCIPisInfinity(scip, consdata->maxactdelta) )
11609  return SCIP_OKAY;
11610 
11611  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11612  * but the eventsystem seems to be full
11613  */
11614  consdata->normalized = FALSE;
11615 
11616  /* normalize constraint */
11617  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11618  assert(nvars == consdata->nvars);
11619 
11620  if( *infeasible )
11621  return SCIP_OKAY;
11622 
11623  if( !consdata->normalized )
11624  return SCIP_OKAY;
11625 
11626  lhs = consdata->lhs;
11627  rhs = consdata->rhs;
11628  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11629  assert(!SCIPisNegative(scip, rhs));
11630 
11631  if( !SCIPisInfinity(scip, -lhs) )
11632  haslhs = TRUE;
11633  else
11634  haslhs = FALSE;
11635 
11636  if( !SCIPisInfinity(scip, rhs) )
11637  hasrhs = TRUE;
11638  else
11639  hasrhs = FALSE;
11640 
11641  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11642  SCIPdebug( oldnchgsides = *nchgsides; )
11643 
11644  /* @todo extend both-sided simplification */
11645  if( haslhs && hasrhs )
11646  {
11647  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11648 
11649  return SCIP_OKAY;
11650  }
11651  assert(haslhs != hasrhs);
11652 
11653  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11654  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11655  assert(!haslhs || !SCIPisNegative(scip, lhs));
11656 
11657  /* get temporary memory to store the sorted permutation */
11658  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11659 
11660  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11661  * value of their coefficients
11662  */
11663  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11664 
11665  /* perform sorting after permutation array */
11666  permSortConsdata(consdata, perm, nvars);
11667  consdata->indexsorted = FALSE;
11668  consdata->coefsorted = FALSE;
11669 
11670  vars = consdata->vars;
11671  vals = consdata->vals;
11672  assert(vars != NULL);
11673  assert(vals != NULL);
11674  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11675 
11676  /* free temporary memory */
11677  SCIPfreeBufferArray(scip, &perm);
11678 
11679  /* only check constraints with at least two non continuous variables */
11680  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11681  return SCIP_OKAY;
11682 
11683  /* do not process constraints when all coefficients are 1.0 */
11684  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11685  return SCIP_OKAY;
11686 
11687  feastol = SCIPfeastol(scip);
11688 
11689  SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11690  SCIPdebugPrintCons(scip, cons, NULL);
11691 
11692  /* get global activities */
11693  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11694  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11695 
11696  /* cannot work with infinite activities */
11697  if( isminsettoinfinity || ismaxsettoinfinity )
11698  return SCIP_OKAY;
11699 
11700  assert(!isminrelax);
11701  assert(!ismaxrelax);
11702  assert(maxact > minact);
11703  assert(!SCIPisInfinity(scip, -minact));
11704  assert(!SCIPisInfinity(scip, maxact));
11705 
11706  v = 0;
11707  offsetv = -1;
11708  side = haslhs ? lhs : rhs;
11709  minactsub = minact;
11710  maxactsub = maxact;
11711 
11712  /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11713  * do not need to look at the large coefficients
11714  *
11715  * e.g. all x are binary, z are positive integer
11716  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11717  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11718  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11719  *
11720  * can be changed to
11721  *
11722  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11723  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11724  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11725  */
11726 
11727  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11728  * hand side, we cannot apply the extra reduction step and need to reset v
11729  *
11730  * 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
11731  * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11732  * for all i is a solution
11733  *
11734  * also redundancy of variables would not be correctly determined in such a case
11735  */
11736  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11737  {
11738  v = 1;
11739 
11740  while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11741  {
11742  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11743  * extra step, which might have worked
11744  */
11745  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11746  {
11747  v = 0;
11748  break;
11749  }
11750 
11751  ++v;
11752  }
11753 
11754  /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11755  /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11756  if( v == nvars )
11757  return SCIP_OKAY;
11758 
11759  /* cannot work with continuous variables which have a big coefficient */
11760  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11761  return SCIP_OKAY;
11762 
11763  /* big negative coefficient, do not try to use the extra coefficient reduction step */
11764  if( SCIPisEQ(scip, side, -vals[v]) )
11765  v = 0;
11766 
11767  /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11768  * reduction
11769  */
11770  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11771  v = 0;
11772 
11773  if( v > 0 )
11774  {
11775  assert(v < nvars);
11776 
11777  offsetv = v - 1;
11778 
11779  for( w = 0; w < v; ++w )
11780  {
11781  lb = SCIPvarGetLbGlobal(vars[w]);
11782  ub = SCIPvarGetUbGlobal(vars[w]);
11783 
11784  assert(vals[w] > 0);
11785 
11786  /* update residual activities */
11787  maxactsub -= ub * vals[w];
11788  minactsub -= lb * vals[w];
11789  assert(maxactsub > minactsub);
11790  }
11791  }
11792  }
11793 
11794  /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11795  *
11796  * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11797  *
11798  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11799  * to
11800  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11801  */
11802  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11803  {
11804  SCIP_Bool redundant = FALSE;
11805  SCIP_Bool numericsok;
11806  SCIP_Bool rredundant;
11807  SCIP_Bool lredundant;
11808 
11809  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11810  assert(gcd >= 1);
11811 
11812  if( v == 0 )
11813  {
11814  lb = SCIPvarGetLbGlobal(vars[0]);
11815  ub = SCIPvarGetUbGlobal(vars[0]);
11816 
11817  /* update residual activities */
11818  if( vals[0] > 0 )
11819  {
11820  maxactsub -= ub * vals[0];
11821  minactsub -= lb * vals[0];
11822  }
11823  else
11824  {
11825  maxactsub -= lb * vals[0];
11826  minactsub -= ub * vals[0];
11827  }
11828  assert(maxactsub > minactsub);
11829  ++v;
11830  }
11831 
11832  siderest = -SCIP_INVALID;
11833  allcoefintegral = TRUE;
11834 
11835  /* check if some variables always fit into the given constraint */
11836  for( ; v < nvars - 1; ++v )
11837  {
11838  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11839  break;
11840 
11841  if( !SCIPisIntegral(scip, vals[v]) )
11842  {
11843  allcoefintegral = FALSE;
11844  break;
11845  }
11846 
11847  /* calculate greatest common divisor for all general and binary variables */
11848  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11849 
11850  if( gcd == 1 )
11851  break;
11852 
11853  lb = SCIPvarGetLbGlobal(vars[v]);
11854  ub = SCIPvarGetUbGlobal(vars[v]);
11855 
11856  assert(!SCIPisInfinity(scip, -lb));
11857  assert(!SCIPisInfinity(scip, ub));
11858 
11859  /* update residual activities */
11860  if( vals[v] > 0 )
11861  {
11862  maxactsub -= ub * vals[v];
11863  minactsub -= lb * vals[v];
11864  }
11865  else
11866  {
11867  maxactsub -= lb * vals[v];
11868  minactsub -= ub * vals[v];
11869  }
11870  assert(SCIPisGE(scip, maxactsub, minactsub));
11871 
11872  if( hasrhs )
11873  {
11874  /* determine the remainder of the right hand side and the gcd */
11875  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11876  }
11877  else
11878  {
11879  /* determine the remainder of the left hand side and the gcd */
11880  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11881  if( SCIPisZero(scip, siderest) )
11882  siderest = gcd;
11883  }
11884 
11885  rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11886  lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11887 
11888  /* early termination if the activities deceed the gcd */
11889  if( offsetv == -1 && (rredundant || lredundant) )
11890  {
11891  redundant = TRUE;
11892  break;
11893  }
11894  }
11895  assert(v < nvars || (offsetv >= 0 && gcd > 1));
11896 
11897  if( !redundant )
11898  {
11899  if( hasrhs )
11900  {
11901  /* determine the remainder of the right hand side and the gcd */
11902  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11903  }
11904  else
11905  {
11906  /* determine the remainder of the left hand side and the gcd */
11907  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11908  if( SCIPisZero(scip, siderest) )
11909  siderest = gcd;
11910  }
11911  }
11912  else
11913  ++v;
11914 
11915  SCIPdebugMsg(scip, "stopped at pos %d (of %d), subactivities [%g, %g], redundant = %u, hasrhs = %u, siderest = %g, gcd = %" SCIP_LONGINT_FORMAT ", offset position for 'side' coefficients = %d\n",
11916  v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11917 
11918  /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11919  * reasonable absolute values */
11920  numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11921  REALABS(minactsub) < MAXACTVAL;
11922 
11923  rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11924  lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11925 
11926  /* check if we can remove redundant variables */
11927  if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11928  {
11929  SCIP_Real oldcoef;
11930 
11931  /* double check the redundancy */
11932 #ifndef NDEBUG
11933  SCIP_Real tmpminactsub = 0.0;
11934  SCIP_Real tmpmaxactsub = 0.0;
11935 
11936  /* recompute residual activities */
11937  for( w = v; w < nvars; ++w )
11938  {
11939  lb = SCIPvarGetLbGlobal(vars[w]);
11940  ub = SCIPvarGetUbGlobal(vars[w]);
11941 
11942  assert(!SCIPisInfinity(scip, -lb));
11943  assert(!SCIPisInfinity(scip, ub));
11944 
11945  /* update residual activities */
11946  if( vals[w] > 0 )
11947  {
11948  tmpmaxactsub += ub * vals[w];
11949  tmpminactsub += lb * vals[w];
11950  }
11951  else
11952  {
11953  tmpmaxactsub += lb * vals[w];
11954  tmpminactsub += ub * vals[w];
11955  }
11956  assert(tmpmaxactsub >= tmpminactsub);
11957  }
11958 
11959  if( hasrhs )
11960  {
11961  assert(offsetv == -1);
11962 
11963  /* determine the remainder of the right hand side and the gcd */
11964  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11965  }
11966  else
11967  {
11968  /* determine the remainder of the left hand side and the gcd */
11969  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11970  if( SCIPisZero(scip, siderest) )
11971  siderest = gcd;
11972  }
11973 
11974  /* is the redundancy really fulfilled */
11975  assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11976  (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11977 #endif
11978 
11979  SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11980  nvars - v, SCIPconsGetName(cons));
11981 
11982  /* remove redundant variables */
11983  for( w = nvars - 1; w >= v; --w )
11984  {
11985  SCIP_CALL( delCoefPos(scip, cons, w) );
11986  }
11987  (*nchgcoefs) += (nvars - v);
11988 
11989  assert(w >= 0);
11990 
11991  oldcoef = vals[w];
11992 
11993  /* normalize constraint */
11994  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11995  assert(vars == consdata->vars);
11996  assert(vals == consdata->vals);
11997  assert(w < consdata->nvars);
11998 
11999  if( *infeasible )
12000  return SCIP_OKAY;
12001 
12002  /* compute new greatest common divisor due to normalization */
12003  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
12004  assert(gcd >= 1);
12005 
12006  /* update side */
12007  if( hasrhs )
12008  {
12009  /* replace old with new right hand side */
12010  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
12011  rhs = consdata->rhs;
12012  }
12013  else
12014  {
12015  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
12016  {
12017  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
12018  lhs = consdata->lhs;
12019  }
12020  else
12021  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
12022  }
12023  ++(*nchgsides);
12024 
12025  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12026  assert(!haslhs || !SCIPisNegative(scip, lhs));
12027 
12028  /* get new constraint data */
12029  nvars = consdata->nvars;
12030  assert(nvars > 0);
12031 
12032  allcoefintegral = TRUE;
12033 
12034 #ifndef NDEBUG
12035  /* check integrality */
12036  for( w = offsetv + 1; w < nvars; ++w )
12037  {
12038  assert(SCIPisIntegral(scip, vals[w]));
12039  }
12040 #endif
12041  SCIPdebugPrintCons(scip, cons, NULL);
12042  }
12043 
12044  /* try to find a better gcd, when having large coefficients */
12045  if( offsetv >= 0 && gcd == 1 )
12046  {
12047  /* calculate greatest common divisor for all general variables */
12048  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
12049 
12050  if( gcd > 1 )
12051  {
12052  gcd = -1;
12053  candpos = -1;
12054 
12055  for( v = nvars - 1; v > offsetv; --v )
12056  {
12057  assert(!SCIPisZero(scip, vals[v]));
12058  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
12059  break;
12060 
12061  if( !SCIPisIntegral(scip, vals[v]) )
12062  {
12063  allcoefintegral = FALSE;
12064  break;
12065  }
12066 
12067  oldgcd = gcd;
12068 
12069  if( gcd == -1 )
12070  {
12071  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12072  assert(gcd >= 1);
12073  }
12074  else
12075  {
12076  /* calculate greatest common divisor for all general and binary variables */
12077  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12078  }
12079 
12080  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12081  * can stop searching
12082  */
12083  if( gcd == 1 )
12084  {
12085  if( !SCIPvarIsBinary(vars[v]) )
12086  break;
12087 
12088  /* found candidate */
12089  if( candpos == -1 )
12090  {
12091  gcd = oldgcd;
12092  candpos = v;
12093  }
12094  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12095  else
12096  break;
12097  }
12098  }
12099  assert(v > offsetv || candpos > offsetv);
12100  }
12101  else
12102  candpos = -1;
12103  }
12104  else
12105  candpos = nvars - 1;
12106 
12107  /* check last coefficient for integrality */
12108  if( gcd > 1 && allcoefintegral && !redundant )
12109  {
12110  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12111  allcoefintegral = FALSE;
12112  }
12113 
12114  /* check for further necessary coefficient adjustments */
12115  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12116  {
12117  assert(offsetv + 1 < nvars);
12118  assert(0 <= candpos && candpos < nvars);
12119 
12120  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12121  {
12122  SCIP_Bool notchangable = FALSE;
12123 
12124 #ifndef NDEBUG
12125  /* check integrality */
12126  for( w = offsetv + 1; w < nvars; ++w )
12127  {
12128  assert(SCIPisIntegral(scip, vals[w]));
12129  }
12130 #endif
12131 
12132  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12133  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12134  {
12135  /* determine the remainder of the side and the gcd */
12136  if( hasrhs )
12137  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12138  else
12139  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12140  assert(rest >= 0);
12141  assert(rest < gcd);
12142 
12143  /* determine the remainder of the coefficient candidate and the gcd */
12144  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12145  assert(restcoef >= 1);
12146  assert(restcoef < gcd);
12147 
12148  if( hasrhs )
12149  {
12150  /* calculate new coefficient */
12151  if( restcoef > rest )
12152  newcoef = vals[candpos] - restcoef + gcd;
12153  else
12154  newcoef = vals[candpos] - restcoef;
12155  }
12156  else
12157  {
12158  /* calculate new coefficient */
12159  if( rest == 0 || restcoef < rest )
12160  newcoef = vals[candpos] - restcoef;
12161  else
12162  newcoef = vals[candpos] - restcoef + gcd;
12163  }
12164 
12165  /* done */
12166 
12167  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12168  * another with the big coefficient was set to 1
12169  */
12170  if( hasrhs && SCIPisZero(scip, newcoef) )
12171  {
12172  notchangable = TRUE;
12173  }
12174  else if( SCIPisZero(scip, newcoef) )
12175  {
12176  /* delete old redundant coefficient */
12177  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12178  ++(*nchgcoefs);
12179  }
12180  else
12181  {
12182  /* replace old with new coefficient */
12183  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12184  ++(*nchgcoefs);
12185  }
12186  }
12187  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12188  {
12189  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12190  }
12191 
12192  /* correct side and big coefficients */
12193  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12194  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12195  {
12196  if( haslhs )
12197  {
12198  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12199 
12200  SCIP_CALL( chgLhs(scip, cons, newcoef) );
12201  ++(*nchgsides);
12202  }
12203  else
12204  {
12205  assert(hasrhs);
12206  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12207 
12208  SCIP_CALL( chgRhs(scip, cons, newcoef) );
12209  ++(*nchgsides);
12210  }
12211 
12212  /* correct coefficients up front */
12213  for( w = offsetv; w >= 0; --w )
12214  {
12215  assert(vals[w] > 0);
12216 
12217  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12218  }
12219  (*nchgcoefs) += (offsetv + 1);
12220  }
12221 
12222  if( !notchangable )
12223  {
12224  /* normalize constraint */
12225  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12226  assert(vars == consdata->vars);
12227  assert(vals == consdata->vals);
12228 
12229  if( *infeasible )
12230  return SCIP_OKAY;
12231 
12232  /* get new constraint data */
12233  nvars = consdata->nvars;
12234  assert(nvars >= 2);
12235 
12236  SCIPdebugPrintCons(scip, cons, NULL);
12237 
12238  lhs = consdata->lhs;
12239  rhs = consdata->rhs;
12240  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12241  assert(!haslhs || !SCIPisNegative(scip, lhs));
12242  }
12243  }
12244  }
12245  }
12246 
12247  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12248  /* no continuous variables are left over */
12249  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12250  return SCIP_OKAY;
12251 
12252  onlybin = TRUE;
12253  allcoefintegral = TRUE;
12254  /* check if all variables are of binary type */
12255  for( v = nvars - 1; v >= 0; --v )
12256  {
12257  if( !SCIPvarIsBinary(vars[v]) )
12258  onlybin = FALSE;
12259  if( !SCIPisIntegral(scip, vals[v]) )
12260  allcoefintegral = FALSE;
12261  }
12262 
12263  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12264  * hand side or bigger than the left hand side respectively, so we can make all of them integral
12265  *
12266  * @todo there are some steps missing ....
12267  */
12268  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12269  {
12270  SCIP_Real val;
12271  SCIP_Real newval;
12272  SCIP_Real frac = 0.0;
12273  SCIP_Bool found = FALSE;
12274 
12275  if( hasrhs )
12276  {
12277  if( allcoefintegral )
12278  {
12279  /* replace old with new right hand side */
12280  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12281  ++(*nchgsides);
12282  }
12283  else
12284  {
12285  siderest = rhs - SCIPfloor(scip, rhs);
12286 
12287  /* try to round down all non-integral coefficients */
12288  for( v = nvars - 1; v >= 0; --v )
12289  {
12290  val = vals[v];
12291 
12292  /* add up all possible fractional parts */
12293  if( !SCIPisIntegral(scip, val) )
12294  {
12295  lb = SCIPvarGetLbGlobal(vars[v]);
12296  ub = SCIPvarGetUbGlobal(vars[v]);
12297 
12298  /* at least one bound need to be at zero */
12299  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12300  return SCIP_OKAY;
12301 
12302  /* swap bounds for 'standard' form */
12303  if( !SCIPisFeasZero(scip, lb) )
12304  {
12305  ub = lb;
12306  val *= -1;
12307  }
12308 
12309  found = TRUE;
12310 
12311  frac += (val - SCIPfloor(scip, val)) * ub;
12312 
12313  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12314  *
12315  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12316  * x3, x4 set to 1 would be infeasible but feasible after flooring
12317  */
12318  if( SCIPisGT(scip, frac, siderest) )
12319  return SCIP_OKAY;
12320  }
12321  }
12322  assert(v == -1);
12323 
12324  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12325 
12326  /* round rhs and coefficients to integral values */
12327  if( found )
12328  {
12329  for( v = nvars - 1; v >= 0; --v )
12330  {
12331  val = vals[v];
12332 
12333  /* add the whole fractional part */
12334  if( !SCIPisIntegral(scip, val) )
12335  {
12336  lb = SCIPvarGetLbGlobal(vars[v]);
12337 
12338  if( SCIPisFeasZero(scip, lb) )
12339  newval = SCIPfloor(scip, val);
12340  else
12341  newval = SCIPceil(scip, val);
12342 
12343  if( SCIPisZero(scip, newval) )
12344  {
12345  /* delete old redundant coefficient */
12346  SCIP_CALL( delCoefPos(scip, cons, v) );
12347  ++(*nchgcoefs);
12348  }
12349  else
12350  {
12351  /* replace old with new coefficient */
12352  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12353  ++(*nchgcoefs);
12354  }
12355  }
12356  }
12357  }
12358 
12359  /* replace old with new right hand side */
12360  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12361  ++(*nchgsides);
12362  }
12363  }
12364  else
12365  {
12366  if( allcoefintegral )
12367  {
12368  /* replace old with new left hand side */
12369  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12370  ++(*nchgsides);
12371  }
12372  else
12373  {
12374  /* cannot floor left hand side to zero */
12375  if( SCIPisLT(scip, lhs, 1.0) )
12376  return SCIP_OKAY;
12377 
12378  siderest = lhs - SCIPfloor(scip, lhs);
12379 
12380  /* try to round down all non-integral coefficients */
12381  for( v = nvars - 1; v >= 0; --v )
12382  {
12383  val = vals[v];
12384 
12385  /* add up all possible fractional parts */
12386  if( !SCIPisIntegral(scip, val) )
12387  {
12388  lb = SCIPvarGetLbGlobal(vars[v]);
12389  ub = SCIPvarGetUbGlobal(vars[v]);
12390 
12391  /* at least one bound need to be at zero */
12392  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12393  return SCIP_OKAY;
12394 
12395  /* swap bounds for 'standard' form */
12396  if( !SCIPisFeasZero(scip, lb) )
12397  {
12398  ub = lb;
12399  val *= -1;
12400  }
12401 
12402  /* cannot floor to zero */
12403  if( SCIPisLT(scip, val, 1.0) )
12404  return SCIP_OKAY;
12405 
12406  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12407  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12408  return SCIP_OKAY;
12409 
12410  found = TRUE;
12411 
12412  frac += (val - SCIPfloor(scip, val)) * ub;
12413 
12414  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12415  * fractional parts of the variables, we cannot tighten the coefficients
12416  *
12417  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12418  * x2-x4 set to 1 would be feasible but not after flooring
12419  */
12420  if( SCIPisGE(scip, frac, 1 + siderest) )
12421  return SCIP_OKAY;
12422  }
12423  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12424  else
12425  return SCIP_OKAY;
12426  }
12427  assert(v == -1);
12428 
12429  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12430 
12431  /* round lhs and coefficients to integral values */
12432  if( found )
12433  {
12434  for( v = nvars - 1; v >= 0; --v )
12435  {
12436  val = vals[v];
12437 
12438  /* add the whole fractional part */
12439  if( !SCIPisIntegral(scip, val) )
12440  {
12441  lb = SCIPvarGetLbGlobal(vars[v]);
12442 
12443  if( SCIPisFeasZero(scip, lb) )
12444  newval = SCIPfloor(scip, val);
12445  else
12446  newval = SCIPceil(scip, val);
12447 
12448  if( SCIPisZero(scip, newval) )
12449  {
12450  /* delete old redundant coefficient */
12451  SCIP_CALL( delCoefPos(scip, cons, v) );
12452  ++(*nchgcoefs);
12453  }
12454  else
12455  {
12456  /* replace old with new coefficient */
12457  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12458  ++(*nchgcoefs);
12459  }
12460  }
12461  }
12462  }
12463 
12464  /* replace old with new left hand side */
12465  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12466  ++(*nchgsides);
12467  }
12468  }
12469 
12470  /* normalize constraint */
12471  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12472  assert(vars == consdata->vars);
12473  assert(vals == consdata->vals);
12474 
12475  if( *infeasible )
12476  return SCIP_OKAY;
12477 
12478  rhs = consdata->rhs;
12479  lhs = consdata->lhs;
12480 
12481  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12482  assert(!haslhs || !SCIPisNegative(scip, lhs));
12483 
12484  SCIPdebugPrintCons(scip, cons, NULL);
12485 
12486  nvars = consdata->nvars;
12487  if( nvars < 2 )
12488  return SCIP_OKAY;
12489 
12490  allcoefintegral = TRUE;
12491 #ifndef NDEBUG
12492  /* debug check if all coefficients are really integral */
12493  for( v = nvars - 1; v >= 0; --v )
12494  assert(SCIPisIntegral(scip, vals[v]));
12495 #endif
12496  }
12497 
12498  /* @todo following can also work on non integral coefficients, need more investigation */
12499  /* only check constraints with integral coefficients on all integral variables */
12500  if( !allcoefintegral )
12501  return SCIP_OKAY;
12502 
12503  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12504  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12505  return SCIP_OKAY;
12506 
12507  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12508  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12509  return SCIP_OKAY;
12510 
12511  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12512  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12513  return SCIP_OKAY;
12514 
12515  assert(nvars >= 2);
12516 
12517  /* start gcd procedure for all variables */
12518  do
12519  {
12520  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12521  SCIPdebug( oldnchgsides = *nchgsides; )
12522 
12523  /* stop if we have two coeffcients which are one in absolute value */
12524  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12525  return SCIP_OKAY;
12526 
12527  gcd = -1;
12528 
12529  /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12530  * because coefficients of non-binary variables might have changed to zero */
12531  if( !onlybin )
12532  {
12533  foundbin = -1;
12534  onlybin = TRUE;
12535 
12536  for( v = nvars - 1; v >= 0; --v )
12537  {
12538  assert(!SCIPisZero(scip, vals[v]));
12539  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12540 
12541  if( SCIPvarIsBinary(vars[v]) )
12542  {
12543  if( foundbin == -1 )
12544  foundbin = v;
12545  continue;
12546  }
12547  else
12548  onlybin = FALSE;
12549 
12550  absval = REALABS(vals[v]);
12551  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12552  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12553  */
12554  assert(SCIPisFeasIntegral(scip, absval));
12555 
12556  if( gcd == -1 )
12557  {
12558  gcd = (SCIP_Longint)(absval + feastol);
12559  assert(gcd >= 1);
12560  }
12561  else
12562  {
12563  /* calculate greatest common divisor for all general variables */
12564  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12565  }
12566  if( gcd == 1 )
12567  break;
12568  }
12569  }
12570  else
12571  foundbin = nvars - 1;
12572 
12573  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12574  if( gcd == 1 || foundbin == -1)
12575  return SCIP_OKAY;
12576 
12577  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12578 
12579  candpos = -1;
12580  candpos2 = -1;
12581 
12582  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12583  * change the coefficient
12584  */
12585  for( v = foundbin; v >= 0; --v )
12586  {
12587  if( onlybin || SCIPvarIsBinary(vars[v]) )
12588  {
12589  absval = REALABS(vals[v]);
12590  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12591  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12592  */
12593  assert(SCIPisFeasIntegral(scip, absval));
12594 
12595  oldgcd = gcd;
12596 
12597  if( gcd == -1 )
12598  {
12599  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12600  assert(gcd >= 1);
12601  }
12602  else
12603  {
12604  /* calculate greatest common divisor for all general and binary variables */
12605  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12606  }
12607 
12608  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12609  * can terminate
12610  */
12611  if( gcd == 1 )
12612  {
12613  /* found candidate */
12614  if( candpos == -1 )
12615  {
12616  gcd = oldgcd;
12617  candpos = v;
12618 
12619  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12620  * the coefficient change
12621  */
12622  if( onlybin && v == foundbin - 1 )
12623  candpos2 = foundbin;
12624  }
12625  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12626  else
12627  {
12628  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12629  {
12630  assert(candpos2 == nvars - 1);
12631 
12632  /* take new candidates */
12633  candpos = candpos2;
12634 
12635  /* recalculate gcd from scratch */
12636  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12637  assert(gcd >= 1);
12638 
12639  /* calculate greatest common divisor for all general and binary variables */
12640  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12641  if( gcd == 1 )
12642  return SCIP_OKAY;
12643  }
12644  else
12645  /* cannot determine a possible coefficient for reduction */
12646  return SCIP_OKAY;
12647  }
12648  }
12649  }
12650  }
12651  assert(gcd >= 2);
12652 
12653  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12654  * further
12655  */
12656  assert(candpos >= 0 && candpos < nvars);
12657 
12658  /* all variables and all coefficients are integral, so the side should be too */
12659  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12660 
12661  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12662  * @see normalizeCons()
12663  */
12664  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12665  assert(!haslhs || !SCIPisNegative(scip, lhs));
12666 
12667  /* determine the remainder of the side and the gcd */
12668  if( hasrhs )
12669  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12670  else
12671  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12672  assert(rest >= 0);
12673  assert(rest < gcd);
12674 
12675  /* determine the remainder of the coefficient candidate and the gcd */
12676  if( vals[candpos] < 0 )
12677  {
12678  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12679  assert(restcoef <= -1);
12680  restcoef += gcd;
12681  }
12682  else
12683  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12684  assert(restcoef >= 1);
12685  assert(restcoef < gcd);
12686 
12687  if( hasrhs )
12688  {
12689  if( rest > 0 )
12690  {
12691  /* replace old with new right hand side */
12692  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12693  ++(*nchgsides);
12694  }
12695 
12696  /* calculate new coefficient */
12697  if( restcoef > rest )
12698  newcoef = vals[candpos] - restcoef + gcd;
12699  else
12700  newcoef = vals[candpos] - restcoef;
12701  }
12702  else
12703  {
12704  if( rest > 0 )
12705  {
12706  /* replace old with new left hand side */
12707  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12708  ++(*nchgsides);
12709  }
12710 
12711  /* calculate new coefficient */
12712  if( rest == 0 || restcoef < rest )
12713  newcoef = vals[candpos] - restcoef;
12714  else
12715  newcoef = vals[candpos] - restcoef + gcd;
12716  }
12717  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12718 
12719  SCIPdebugMsg(scip, "gcd = %" SCIP_LONGINT_FORMAT ", rest = %" SCIP_LONGINT_FORMAT ", restcoef = %" SCIP_LONGINT_FORMAT "; changing coef of variable <%s> to %g and %s by %" SCIP_LONGINT_FORMAT "\n", gcd, rest, restcoef, SCIPvarGetName(vars[candpos]), newcoef, hasrhs ? "reduced rhs" : "increased lhs", hasrhs ? rest : (rest > 0 ? gcd - rest : 0));
12720 
12721  if( SCIPisZero(scip, newcoef) )
12722  {
12723  /* delete redundant coefficient */
12724  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12725  }
12726  else
12727  {
12728  /* replace old with new coefficient */
12729  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12730  }
12731  ++(*nchgcoefs);
12732 
12733  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12734  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12735  assert(vars == consdata->vars);
12736  assert(vals == consdata->vals);
12737 
12738  if( *infeasible )
12739  return SCIP_OKAY;
12740 
12741  SCIPdebugPrintCons(scip, cons, NULL);
12742 
12743  rhs = consdata->rhs;
12744  lhs = consdata->lhs;
12745  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12746  assert(!haslhs || !SCIPisNegative(scip, lhs));
12747 
12748  nvars = consdata->nvars;
12749 
12750  SCIPdebugMsg(scip, "we did %d coefficient changes and %d side changes on constraint %s when applying one round of the gcd algorithm\n", *nchgcoefs - oldnchgcoefs, *nchgsides - oldnchgsides, SCIPconsGetName(cons));
12751  }
12752  while( nvars >= 2 );
12753 
12754  return SCIP_OKAY;
12755 }
12756 
12757 
12758 /** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12759  * cons0 := a * cons0 + b * cons1,
12760  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12761  * for numerical stability, we will only accept integral a and b;
12762  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12763  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12764  */
12765 static
12767  SCIP* scip, /**< SCIP data structure */
12768  SCIP_CONS* cons0, /**< (in)equality to modify */
12769  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12770  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12771  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12772  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12773  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12774  int nvarscommon, /**< number of variables, that appear in both constraints */
12775  int commonidxweight, /**< variable weight sum of common variables */
12776  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12777  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12778  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12779  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12780  SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12781  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12782  )
12783 {
12784  SCIP_CONSDATA* consdata0;
12785  SCIP_CONSDATA* consdata1;
12786  SCIP_Real a;
12787  SCIP_Real b;
12788  SCIP_Real aggrcoef;
12789  SCIP_Real scalarsum;
12790  SCIP_Real bestscalarsum;
12791  SCIP_Bool betterscalarsum;
12792  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12793  int varweight;
12794  int nvars;
12795  int bestvarweight;
12796  int bestnvars;
12797  int bestv;
12798  int v;
12799  int i;
12800 
12801  assert(scip != NULL);
12802  assert(cons0 != NULL);
12803  assert(cons1 != NULL);
12804  assert(commonidx0 != NULL);
12805  assert(commonidx1 != NULL);
12806  assert(diffidx0minus1 != NULL);
12807  assert(diffidx1minus0 != NULL);
12808  assert(nvarscommon >= 1);
12809  assert(commonidxweight >= nvarscommon);
12810  assert(nchgcoefs != NULL);
12811  assert(aggregated != NULL);
12812 
12813  assert(SCIPconsIsActive(cons0));
12814  assert(SCIPconsIsActive(cons1));
12815 
12816  *infeasible = FALSE;
12817 
12818  SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12819 
12820  /* cons0 is an (in)equality */
12821  consdata0 = SCIPconsGetData(cons0);
12822  assert(consdata0 != NULL);
12823  assert(consdata0->nvars >= 1);
12824  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12825  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12826 
12827  /* cons1 is an equality */
12828  consdata1 = SCIPconsGetData(cons1);
12829  assert(consdata1 != NULL);
12830  assert(consdata1->nvars >= 1);
12831  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12832  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12833 
12834  *aggregated = FALSE;
12835 
12836  /* search for the best common variable such that
12837  * val1[var] * consdata0 - val0[var] * consdata1
12838  * has least weighted number of variables
12839  */
12840  bestvarweight = commonidxweight + diffidx0minus1weight;
12841  bestnvars = consdata0->nvars;
12842  bestv = -1;
12843  bestscalarsum = 0.0;
12844  commonvarlindependent = TRUE;
12845  for( v = 0; v < nvarscommon; ++v )
12846  {
12847  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12848  a = consdata1->vals[commonidx1[v]];
12849  b = -consdata0->vals[commonidx0[v]];
12850 
12851  /* only try aggregation, if coefficients are integral (numerical stability) */
12852  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12853  {
12854  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12855  varweight = diffidx0minus1weight + diffidx1minus0weight;
12856  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12857  scalarsum = REALABS(a) + REALABS(b);
12858  betterscalarsum = (scalarsum < bestscalarsum);
12859  for( i = 0; i < nvarscommon
12860  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12861  {
12862  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12863  if( !SCIPisZero(scip, aggrcoef) )
12864  {
12865  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12866  nvars++;
12867  }
12868  }
12869  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12870  {
12871  bestv = v;
12872  bestvarweight = varweight;
12873  bestnvars = nvars;
12874  bestscalarsum = scalarsum;
12875  }
12876  }
12877 
12878  /* update commonvarlindependent flag, if still TRUE:
12879  * v's common coefficient in cons1 / v's common coefficient in cons0 should be constant, i.e., equal 0's common coefficient in cons1 / 0's common coefficient in cons0
12880  */
12881  if( commonvarlindependent && v > 0 )
12882  commonvarlindependent = SCIPisEQ(scip,
12883  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12884  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12885  }
12886 
12887  /* if better aggregation was found, create new constraint and delete old one */
12888  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12889  {
12890  SCIP_CONS* newcons;
12891  SCIP_CONSDATA* newconsdata;
12892  SCIP_VAR** newvars;
12893  SCIP_Real* newvals;
12894  SCIP_Real newlhs;
12895  SCIP_Real newrhs;
12896  int newnvars;
12897 
12898  if( bestv != -1 )
12899  {
12900  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12901  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12902  {
12903  a = consdata1->vals[commonidx1[bestv]];
12904  b = -consdata0->vals[commonidx0[bestv]];
12905  }
12906  else
12907  {
12908  a = -consdata1->vals[commonidx1[bestv]];
12909  b = consdata0->vals[commonidx0[bestv]];
12910  }
12911  assert(SCIPisIntegral(scip, a));
12912  assert(SCIPisPositive(scip, a));
12913  assert(SCIPisIntegral(scip, b));
12914  assert(!SCIPisZero(scip, b));
12915  }
12916  else
12917  {
12918  assert(commonvarlindependent);
12919  if( consdata1->vals[commonidx1[0]] > 0.0 )
12920  {
12921  a = consdata1->vals[commonidx1[0]];
12922  b = -consdata0->vals[commonidx0[0]];
12923  }
12924  else
12925  {
12926  a = -consdata1->vals[commonidx1[0]];
12927  b = consdata0->vals[commonidx0[0]];
12928  }
12929  assert(SCIPisPositive(scip, a));
12930  assert(!SCIPisZero(scip, b));
12931 
12932  /* if a/b is integral, then we can easily choose integer multipliers */
12933  if( SCIPisIntegral(scip, a/b) )
12934  {
12935  if( a/b > 0 )
12936  {
12937  a /= b;
12938  b = 1.0;
12939  }
12940  else
12941  {
12942  a /= -b;
12943  b = -1.0;
12944  }
12945  }
12946 
12947  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12948  SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12949  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12950  }
12951 
12952  SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12953  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12954  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12955  SCIPdebugPrintCons(scip, cons0, NULL);
12956  SCIPdebugPrintCons(scip, cons1, NULL);
12957 
12958  /* get temporary memory for creating the new linear constraint */
12959  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12960  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12961 
12962  /* calculate the common coefficients, if we have not recognized linear dependency */
12963  newnvars = 0;
12964  if( !commonvarlindependent )
12965  {
12966  for( i = 0; i < nvarscommon; ++i )
12967  {
12968  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12969  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12970 
12971  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12972  if( !SCIPisZero(scip, aggrcoef) )
12973  {
12974  assert(newnvars < bestnvars);
12975  newvars[newnvars] = consdata0->vars[commonidx0[i]];
12976  newvals[newnvars] = aggrcoef;
12977  newnvars++;
12978  }
12979  }
12980  }
12981  else
12982  {
12983  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12984 #ifndef NDEBUG
12985  for( i = 0; i < nvarscommon; ++i )
12986  {
12987  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12988  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12989 
12990  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12991  assert(SCIPisZero(scip, aggrcoef));
12992  }
12993 #endif
12994  }
12995 
12996  /* calculate the coefficients appearing in cons0 but not in cons1 */
12997  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12998  {
12999  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
13000 
13001  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
13002  assert(!SCIPisZero(scip, aggrcoef));
13003  assert(newnvars < bestnvars);
13004  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
13005  newvals[newnvars] = aggrcoef;
13006  newnvars++;
13007  }
13008 
13009  /* calculate the coefficients appearing in cons1 but not in cons0 */
13010  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
13011  {
13012  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
13013 
13014  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
13015  assert(!SCIPisZero(scip, aggrcoef));
13016  assert(newnvars < bestnvars);
13017  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
13018  newvals[newnvars] = aggrcoef;
13019  newnvars++;
13020  }
13021  assert(newnvars == bestnvars);
13022 
13023  /* calculate the new left and right hand side of the (in)equality */
13024  assert(!SCIPisInfinity(scip, -consdata1->lhs));
13025  assert(!SCIPisInfinity(scip, consdata1->rhs));
13026  if( SCIPisInfinity(scip, -consdata0->lhs) )
13027  newlhs = -SCIPinfinity(scip);
13028  else
13029  newlhs = a * consdata0->lhs + b * consdata1->lhs;
13030  if( SCIPisInfinity(scip, consdata0->rhs) )
13031  newrhs = SCIPinfinity(scip);
13032  else
13033  newrhs = a * consdata0->rhs + b * consdata1->rhs;
13034 
13035  /* create the new linear constraint */
13036  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
13038  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
13039  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
13041 
13042  newconsdata = SCIPconsGetData(newcons);
13043  assert(newconsdata != NULL);
13044 
13045  /* copy the upgraded flag from the old cons0 to the new constraint */
13046  newconsdata->upgraded = consdata0->upgraded;
13047 
13048  /* normalize the new constraint */
13049  SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
13050 
13051  if( *infeasible )
13052  goto TERMINATE;
13053 
13054  /* check, if we really want to use the new constraint instead of the old one:
13055  * use the new one, if the maximum norm doesn't grow too much
13056  */
13057  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
13058  {
13059  SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
13060  SCIPdebugPrintCons(scip, newcons, NULL);
13061 
13062  /* update the statistics: we changed all coefficients */
13063  if( !consdata0->upgraded )
13064  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
13065  *aggregated = TRUE;
13066 
13067  /* delete the old constraint, and add the new linear constraint to the problem */
13068  SCIP_CALL( SCIPdelCons(scip, cons0) );
13069  SCIP_CALL( SCIPaddCons(scip, newcons) );
13070  }
13071 
13072  TERMINATE:
13073  /* release the new constraint */
13074  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
13075 
13076  /* free temporary memory */
13077  SCIPfreeBufferArray(scip, &newvals);
13078  SCIPfreeBufferArray(scip, &newvars);
13079  }
13080 
13081  return SCIP_OKAY;
13082 }
13083 
13084 /** gets the key of the given element */
13085 static
13086 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
13087 { /*lint --e{715}*/
13088  /* the key is the element itself */
13089  return elem;
13090 }
13091 
13092 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13093  * coefficients are either equal or negated
13094  */
13095 static
13096 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
13097 {
13098  SCIP* scip;
13099  SCIP_CONSDATA* consdata1;
13100  SCIP_CONSDATA* consdata2;
13101  SCIP_Real cons1scale;
13102  SCIP_Real cons2scale;
13103  int i;
13104 
13105  assert(key1 != NULL);
13106  assert(key2 != NULL);
13107  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13108  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13109  assert(consdata1->indexsorted);
13110  assert(consdata2->indexsorted);
13111 
13112  scip = (SCIP*)userptr;
13113  assert(scip != NULL);
13114 
13115  /* if it is the same constraint we dont need to check anything */
13116  if( key1 == key2 )
13117  return TRUE;
13118 
13119  /* checks trivial case */
13120  if( consdata1->nvars != consdata2->nvars )
13121  return FALSE;
13122 
13123  /* tests if variables are equal */
13124  for( i = 0; i < consdata1->nvars; ++i )
13125  {
13126  if( consdata1->vars[i] != consdata2->vars[i] )
13127  {
13128  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13129  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13130  return FALSE;
13131  }
13132  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13133  }
13134 
13135  /* compute scale before comparing coefficients of constraints */
13136  cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
13137  cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
13138 
13139  /* tests if coefficients are equal with the computed scale */
13140  for( i = 0; i < consdata1->nvars; ++i )
13141  {
13142  SCIP_Real val1;
13143  SCIP_Real val2;
13144 
13145  val1 = consdata1->vals[i] * cons1scale;
13146  val2 = consdata2->vals[i] * cons2scale;
13147 
13148  if( !SCIPisEQ(scip, val1, val2) )
13149  return FALSE;
13150  }
13151 
13152  return TRUE;
13153 }
13154 
13155 /** returns the hash value of the key */
13156 static
13157 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13158 {
13159  SCIP_CONSDATA* consdata;
13160  int minidx;
13161  int mididx;
13162  int maxidx;
13163  SCIP_Real scale;
13164 #ifndef NDEBUG
13165  SCIP* scip;
13166 
13167  scip = (SCIP*)userptr;
13168  assert(scip != NULL);
13169 #endif
13170 
13171  assert(key != NULL);
13172  consdata = SCIPconsGetData((SCIP_CONS*)key);
13173  assert(consdata != NULL);
13174  assert(consdata->nvars > 0);
13175 
13176  assert(consdata->indexsorted);
13177 
13178  minidx = SCIPvarGetIndex(consdata->vars[0]);
13179  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13180  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13181  scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
13182 
13183  /* using only the variable indices as hash, since the values are compared by epsilon */
13184  return SCIPhashSeven(consdata->nvars, minidx, SCIPrealHashCode(consdata->vals[0] * scale),
13185  mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale),
13186  maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale));
13187 }
13188 
13189 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13190  * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13191  */
13192 static
13193 unsigned int getParallelConsKey(
13194  SCIP_CONS* cons /**< linear constraint */
13195  )
13196 {
13197  SCIP_CONSDATA* consdata;
13198 
13199  assert(cons != NULL);
13200 
13201  consdata = SCIPconsGetData(cons);
13202  assert(consdata != NULL);
13203 
13204  return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13205 }
13206 
13207 /** updates the hashtable such that out of all constraints in the hashtable that are detected
13208  * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13209  * and all others are removed from the hashtable and stored in the given array
13210  */
13211 static
13213  SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13214  SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13215  * upon return will contain the constraint that should be kept */
13216  SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13217  * these constraints where removed from the hashtable */
13218  int* nparallelconss /**< pointer to return number of parallel constraints */
13219  )
13220 {
13221  SCIP_CONS* parallelcons;
13222  unsigned int querykey;
13223 
13224  *nparallelconss = 0;
13225  querykey = getParallelConsKey(*querycons);
13226 
13227  while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13228  {
13229  unsigned int conskey = getParallelConsKey(parallelcons);
13230 
13231  if( conskey < querykey )
13232  {
13233  parallelconss[(*nparallelconss)++] = *querycons;
13234  *querycons = parallelcons;
13235  querykey = conskey;
13236  }
13237  else
13238  {
13239  parallelconss[(*nparallelconss)++] = parallelcons;
13240  }
13241 
13242  /* if the constraint that just came out of the hash table is the one that is kept,
13243  * we do not need to look into the hashtable again, since the invariant is that
13244  * in the hashtable only pair-wise non-parallel constraints are contained.
13245  * For the original querycons, however, multiple constraints that compare equal (=parallel)
13246  * could be contained due to non-transitivity of the equality comparison.
13247  * Also we can return immediately, since parallelcons is already contained in the
13248  * hashtable and we do not need to remove and reinsert it.
13249  */
13250  if( *querycons == parallelcons )
13251  return SCIP_OKAY;
13252 
13253  /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13254  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13255  }
13256 
13257  /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13258  * comnpares equal to querycons at this point
13259  */
13260 #ifndef NDEBUG
13261  SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13262 #else
13263  SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13264 #endif
13265 
13266  return SCIP_OKAY;
13267 }
13268 
13269 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13270  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13271  */
13272 static
13274  SCIP* scip, /**< SCIP data structure */
13275  BMS_BLKMEM* blkmem, /**< block memory */
13276  SCIP_CONS** conss, /**< constraint set */
13277  int nconss, /**< number of constraints in constraint set */
13278  int* firstchange, /**< pointer to store first changed constraint */
13279  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13280  int* ndelconss, /**< pointer to count number of deleted constraints */
13281  int* nchgsides /**< pointer to count number of changed left/right hand sides */
13282  )
13283 {
13284  SCIP_HASHTABLE* hashtable;
13285  SCIP_CONS** parallelconss;
13286  int nparallelconss;
13287  int hashtablesize;
13288  int c;
13289 
13290  assert(scip != NULL);
13291  assert(blkmem != NULL);
13292  assert(conss != NULL);
13293  assert(firstchange != NULL);
13294  assert(cutoff != NULL);
13295  assert(ndelconss != NULL);
13296  assert(nchgsides != NULL);
13297 
13298  /* create a hash table for the constraint set */
13299  hashtablesize = nconss;
13300  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13301  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13302 
13303  SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13304 
13305  /* check all constraints in the given set for redundancy */
13306  for( c = 0; c < nconss; ++c )
13307  {
13308  SCIP_CONS* cons0;
13309  SCIP_CONSDATA* consdata0;
13310 
13311  cons0 = conss[c];
13312 
13313  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13314  continue;
13315 
13316  /* do not check for parallel constraints if they should not be upgraded */
13317  if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13318  continue;
13319 
13320  /* check for interuption */
13321  if( c % 1000 == 0 && SCIPisStopped(scip) )
13322  break;
13323 
13324  /* sorts the constraint */
13325  consdata0 = SCIPconsGetData(cons0);
13326  assert(consdata0 != NULL);
13327  SCIP_CALL( consdataSort(scip, consdata0) );
13328  assert(consdata0->indexsorted);
13329 
13330  /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13331  * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13332  * first variable is positive
13333  * Also inserts cons0 into the hashtable.
13334  */
13335  SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13336 
13337  if( nparallelconss != 0 )
13338  {
13339  SCIP_Real lhs;
13340  SCIP_Real rhs;
13341 
13342  int i;
13343 
13344  /* cons0 may have been changed in retrieveParallelConstraints() */
13345  consdata0 = SCIPconsGetData(cons0);
13346 
13347  lhs = consdata0->lhs;
13348  rhs = consdata0->rhs;
13349 
13350  for( i = 0; i < nparallelconss; ++i )
13351  {
13352  SCIP_CONS* consdel;
13353  SCIP_CONSDATA* consdatadel;
13354  SCIP_Real scale;
13355 
13356  consdel = parallelconss[i];
13357  consdatadel = SCIPconsGetData(consdel);
13358 
13359  /* do not delete constraint if it should not be upgraded */
13360  if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13361  continue;
13362 
13363  assert(SCIPconsIsActive(consdel));
13364  assert(!SCIPconsIsModifiable(consdel));
13365 
13366  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13367  * delete old constraints afterwards
13368  */
13369  assert(consdatadel != NULL);
13370  assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13371 
13372  assert(consdatadel->indexsorted);
13373  assert(consdata0->vars[0] == consdatadel->vars[0]);
13374 
13375  scale = consdata0->vals[0] / consdatadel->vals[0];
13376  assert(scale != 0.0);
13377 
13378  /* in debug mode, check that all coefficients are equal with respect to epsilon
13379  * if the constraints are in equilibrium scale
13380  */
13381 #ifndef NDEBUG
13382  {
13383  int k;
13384  SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13385  SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13386 
13387  for( k = 0; k < consdata0->nvars; ++k )
13388  {
13389  assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13390  }
13391  }
13392 #endif
13393 
13394  if( scale > 0.0 )
13395  {
13396  /* the coefficients of both constraints are parallel with a positive scale */
13397  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13398  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13399  SCIPdebugPrintCons(scip, cons0, NULL);
13400  SCIPdebugPrintCons(scip, consdel, NULL);
13401 
13402  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13403  lhs = MAX(scale * consdatadel->lhs, lhs);
13404 
13405  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13406  rhs = MIN(scale * consdatadel->rhs, rhs);
13407  }
13408  else
13409  {
13410  /* the coefficients of both rows are negations */
13411  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13412  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13413  SCIPdebugPrintCons(scip, cons0, NULL);
13414  SCIPdebugPrintCons(scip, consdel, NULL);
13415 
13416  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13417  lhs = MAX(scale * consdatadel->rhs, lhs);
13418 
13419  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13420  rhs = MIN(scale * consdatadel->lhs, rhs);
13421  }
13422 
13423  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13424  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13425 
13426  /* delete consdel */
13427  assert( ! consdata0->upgraded || consdatadel->upgraded );
13428  SCIP_CALL( SCIPdelCons(scip, consdel) );
13429  if( !consdatadel->upgraded )
13430  (*ndelconss)++;
13431  }
13432 
13433  if( SCIPisFeasLT(scip, rhs, lhs) )
13434  {
13435  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13436  *cutoff = TRUE;
13437  break;
13438  }
13439 
13440  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13441  if( lhs > rhs )
13442  {
13443  rhs = (lhs + rhs)/2;
13444  lhs = rhs;
13445  }
13446 
13447  /* update lhs and rhs of cons0 */
13448  SCIP_CALL( chgLhs(scip, cons0, lhs) );
13449  SCIP_CALL( chgRhs(scip, cons0, rhs) );
13450 
13451  /* update the first changed constraint to begin the next aggregation round with */
13452  if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13453  *firstchange = SCIPconsGetPos(cons0);
13454 
13455  assert(SCIPconsIsActive(cons0));
13456  }
13457  }
13458 #ifdef SCIP_MORE_DEBUG
13459  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13461 #endif
13462 
13463  SCIPfreeBufferArray(scip, &parallelconss);
13464 
13465  /* free hash table */
13466  SCIPhashtableFree(&hashtable);
13467 
13468  return SCIP_OKAY;
13469 }
13470 
13471 /** compares constraint with all prior constraints for possible redundancy or aggregation,
13472  * and removes or changes constraint accordingly
13473  */
13474 static
13476  SCIP* scip, /**< SCIP data structure */
13477  SCIP_CONS** conss, /**< constraint set */
13478  int firstchange, /**< first constraint that changed since last pair preprocessing round */
13479  int chkind, /**< index of constraint to check against all prior indices upto startind */
13480  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13481  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13482  int* ndelconss, /**< pointer to count number of deleted constraints */
13483  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13484  int* nchgcoefs /**< pointer to count number of changed coefficients */
13485  )
13486 {
13487  SCIP_CONS* cons0;
13488  SCIP_CONSDATA* consdata0;
13489  int* commonidx0;
13490  int* commonidx1;
13491  int* diffidx0minus1;
13492  int* diffidx1minus0;
13493  uint64_t possignature0;
13494  uint64_t negsignature0;
13495  SCIP_Bool cons0changed;
13496  SCIP_Bool cons0isequality;
13497  int diffidx1minus0size;
13498  int c;
13499  SCIP_Real cons0lhs;
13500  SCIP_Real cons0rhs;
13501  SCIP_Bool cons0upgraded;
13502 
13503  assert(scip != NULL);
13504  assert(conss != NULL);
13505  assert(firstchange <= chkind);
13506  assert(cutoff != NULL);
13507  assert(ndelconss != NULL);
13508  assert(nchgsides != NULL);
13509  assert(nchgcoefs != NULL);
13510 
13511  /* get the constraint to be checked against all prior constraints */
13512  cons0 = conss[chkind];
13513  assert(cons0 != NULL);
13514  assert(SCIPconsIsActive(cons0));
13515  assert(!SCIPconsIsModifiable(cons0));
13516 
13517  consdata0 = SCIPconsGetData(cons0);
13518  assert(consdata0 != NULL);
13519  assert(consdata0->nvars >= 1);
13520  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13521 
13522  /* sort the constraint */
13523  SCIP_CALL( consdataSort(scip, consdata0) );
13524 
13525  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13526  consdataCalcSignatures(consdata0);
13527  possignature0 = consdata0->possignature;
13528  negsignature0 = consdata0->negsignature;
13529 
13530  /* get temporary memory for indices of common variables */
13531  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13532  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13533  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13534  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13535  diffidx1minus0size = consdata0->nvars;
13536 
13537  cons0lhs = consdata0->lhs;
13538  cons0rhs = consdata0->rhs;
13539  cons0upgraded = consdata0->upgraded;
13540 
13541  /* check constraint against all prior constraints */
13542  cons0changed = consdata0->changed;
13543  consdata0->changed = FALSE;
13544  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13545  {
13546  SCIP_CONS* cons1;
13547  SCIP_CONSDATA* consdata1;
13548  uint64_t possignature1;
13549  uint64_t negsignature1;
13550  SCIP_Bool cons0dominateslhs;
13551  SCIP_Bool cons1dominateslhs;
13552  SCIP_Bool cons0dominatesrhs;
13553  SCIP_Bool cons1dominatesrhs;
13554  SCIP_Bool cons1isequality;
13555  SCIP_Bool coefsequal;
13556  SCIP_Bool coefsnegated;
13557  SCIP_Bool tryaggregation;
13558  int nvarscommon;
13559  int nvars0minus1;
13560  int nvars1minus0;
13561  int commonidxweight;
13562  int diffidx0minus1weight;
13563  int diffidx1minus0weight;
13564  int v0;
13565  int v1;
13566 
13567  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13568  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13569  assert(cons0upgraded == consdata0->upgraded);
13570 
13571  cons1 = conss[c];
13572 
13573  /* cons1 has become inactive during presolving of constraint pairs */
13574  if( cons1 == NULL )
13575  continue;
13576 
13577  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13578  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13579 
13580  consdata1 = SCIPconsGetData(cons1);
13581  assert(consdata1 != NULL);
13582 
13583  /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13584  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13585  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13586 
13587  /* if both constraints didn't change since last pair processing, we can ignore the pair */
13588  if( !cons0changed && !consdata1->changed )
13589  continue;
13590 
13591  /* if both constraints are already upgraded, skip the pair;
13592  * because changes on these constraints cannot be applied to the instance anymore */
13593  if( cons0upgraded && consdata1->upgraded )
13594  continue;
13595 
13596  assert(consdata1->nvars >= 1);
13597 
13598  /* sort the constraint */
13599  SCIP_CALL( consdataSort(scip, consdata1) );
13600 
13601  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13602  consdataCalcSignatures(consdata1);
13603  possignature1 = consdata1->possignature;
13604  negsignature1 = consdata1->negsignature;
13605 
13606  /* the signatures give a quick test to check for domination and equality of coefficients */
13607  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13608  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13609  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13610  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13611  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13612  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13613  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13614  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13615  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13616  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13617  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13618  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13619  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13620  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13621  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13622  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13623  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13624  && !coefsequal && !coefsnegated && !tryaggregation )
13625  continue;
13626 
13627  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13628  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13629  {
13630  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13631  diffidx1minus0size = consdata1->nvars;
13632  }
13633 
13634  /* check consdata0 against consdata1:
13635  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13636  * consdata0 dominates consdata1 w.r.t. left hand side
13637  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13638  * consdata0 dominates consdata1 w.r.t. right hand side
13639  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13640  * ranged row (or equality)
13641  * - if at least one constraint is an equality, count the weighted number of common variables W_c
13642  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13643  * where the weight of each variable depends on its type, such that aggregations in order to remove the
13644  * number of continuous and integer variables are preferred:
13645  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13646  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13647  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13648  * to be positive to not switch the sense of the (in)equality cons0
13649  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13650  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13651  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13652  * to be positive to not switch the sense of the (in)equality cons1
13653  */
13654 
13655  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13656  nvarscommon = 0;
13657  commonidxweight = 0;
13658  nvars0minus1 = 0;
13659  diffidx0minus1weight = 0;
13660  nvars1minus0 = 0;
13661  diffidx1minus0weight = 0;
13662  v0 = 0;
13663  v1 = 0;
13664  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13665  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13666  || coefsequal || coefsnegated || tryaggregation) )
13667  {
13668  SCIP_VAR* var;
13669  SCIP_Real val0;
13670  SCIP_Real val1;
13671  int varcmp;
13672 
13673  /* test, if variable appears in only one or in both constraints */
13674  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13675  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13676  else if( v0 < consdata0->nvars )
13677  varcmp = -1;
13678  else
13679  varcmp = +1;
13680 
13681  switch( varcmp )
13682  {
13683  case -1:
13684  /* variable doesn't appear in consdata1 */
13685  var = consdata0->vars[v0];
13686  val0 = consdata0->vals[v0];
13687  val1 = 0.0;
13688  if( tryaggregation )
13689  {
13690  diffidx0minus1[nvars0minus1] = v0;
13691  nvars0minus1++;
13692  diffidx0minus1weight += getVarWeight(var);
13693  }
13694  v0++;
13695  coefsequal = FALSE;
13696  coefsnegated = FALSE;
13697  break;
13698 
13699  case +1:
13700  /* variable doesn't appear in consdata0 */
13701  var = consdata1->vars[v1];
13702  val0 = 0.0;
13703  val1 = consdata1->vals[v1];
13704  if( tryaggregation )
13705  {
13706  diffidx1minus0[nvars1minus0] = v1;
13707  nvars1minus0++;
13708  diffidx1minus0weight += getVarWeight(var);
13709  }
13710  v1++;
13711  coefsequal = FALSE;
13712  coefsnegated = FALSE;
13713  break;
13714 
13715  case 0:
13716  /* variable appears in both constraints */
13717  assert(consdata0->vars[v0] == consdata1->vars[v1]);
13718  var = consdata0->vars[v0];
13719  val0 = consdata0->vals[v0];
13720  val1 = consdata1->vals[v1];
13721  if( tryaggregation )
13722  {
13723  commonidx0[nvarscommon] = v0;
13724  commonidx1[nvarscommon] = v1;
13725  nvarscommon++;
13726  commonidxweight += getVarWeight(var);
13727  }
13728  v0++;
13729  v1++;
13730  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13731  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13732  break;
13733 
13734  default:
13735  SCIPerrorMessage("invalid comparison result\n");
13736  SCIPABORT();
13737  var = NULL;
13738  val0 = 0.0;
13739  val1 = 0.0;
13740  }
13741  assert(var != NULL);
13742 
13743  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13744  if( SCIPisGT(scip, val0, val1) )
13745  {
13746  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13747  {
13748  cons0dominatesrhs = FALSE;
13749  cons1dominateslhs = FALSE;
13750  }
13751  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13752  {
13753  cons0dominateslhs = FALSE;
13754  cons1dominatesrhs = FALSE;
13755  }
13756  }
13757  else if( SCIPisLT(scip, val0, val1) )
13758  {
13759  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13760  {
13761  cons0dominateslhs = FALSE;
13762  cons1dominatesrhs = FALSE;
13763  }
13764  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13765  {
13766  cons0dominatesrhs = FALSE;
13767  cons1dominateslhs = FALSE;
13768  }
13769  }
13770  }
13771 
13772  /* check for disaggregated ranged rows */
13773  if( coefsequal || coefsnegated )
13774  {
13775  SCIP_CONS* consstay;
13776  SCIP_CONS* consdel;
13777 #ifndef NDEBUG
13778  SCIP_CONSDATA* consdatastay;
13779 #endif
13780  SCIP_CONSDATA* consdatadel;
13781  SCIP_Real lhs;
13782  SCIP_Real rhs;
13783  int consinddel;
13784 
13785  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13786  * best left and right hand sides; delete the old constraints afterwards
13787  */
13788  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13789  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13790  SCIPdebugPrintCons(scip, cons0, NULL);
13791  SCIPdebugPrintCons(scip, cons1, NULL);
13792 
13793  if( coefsequal )
13794  {
13795  /* the coefficients of both rows are equal */
13796  lhs = MAX(consdata0->lhs, consdata1->lhs);
13797  rhs = MIN(consdata0->rhs, consdata1->rhs);
13798  }
13799  else
13800  {
13801  /* the coefficients of both rows are negations */
13802  lhs = MAX(consdata0->lhs, -consdata1->rhs);
13803  rhs = MIN(consdata0->rhs, -consdata1->lhs);
13804  }
13805  if( SCIPisFeasLT(scip, rhs, lhs) )
13806  {
13807  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13808  *cutoff = TRUE;
13809  break;
13810  }
13811 
13812  /* check which constraint has to stay;
13813  * changes applied to an upgraded constraint will not be considered in the instance */
13814  if( consdata0->upgraded )
13815  {
13816  assert(!consdata1->upgraded);
13817  consstay = cons1;
13818 #ifndef NDEBUG
13819  consdatastay = consdata1;
13820 #endif
13821 
13822  consdel = cons0;
13823  consdatadel = consdata0;
13824  consinddel = chkind;
13825  }
13826  else
13827  {
13828  consstay = cons0;
13829 #ifndef NDEBUG
13830  consdatastay = consdata0;
13831 #endif
13832 
13833  consdel = cons1;
13834  consdatadel = consdata1;
13835  consinddel = c;
13836  }
13837 
13838  /* update the sides of consstay */
13839  SCIP_CALL( chgLhs(scip, consstay, lhs) );
13840  SCIP_CALL( chgRhs(scip, consstay, rhs) );
13841  if( !consdata0->upgraded )
13842  {
13843  assert(consstay == cons0);
13844  cons0lhs = consdata0->lhs;
13845  cons0rhs = consdata0->rhs;
13846  }
13847 
13848  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13849  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13850 
13851  assert( !consdatastay->upgraded );
13852  /* delete consdel */
13853  SCIP_CALL( SCIPdelCons(scip, consdel) );
13854  conss[consinddel] = NULL;
13855  if( !consdatadel->upgraded )
13856  (*ndelconss)++;
13857  continue;
13858  }
13859 
13860  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13861  * redundant
13862  */
13863  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13864  {
13865  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13866  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13867  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13868  SCIPdebugPrintCons(scip, cons0, NULL);
13869  SCIPdebugPrintCons(scip, cons1, NULL);
13870 
13871  /* check for infeasibility */
13872  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13873  {
13874  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13875  *cutoff = TRUE;
13876  break;
13877  }
13878 
13879  /* remove redundant left hand side */
13880  if( !SCIPisInfinity(scip, -consdata0->lhs) )
13881  {
13882  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13883  cons0lhs = consdata0->lhs;
13884  cons0isequality = FALSE;
13885  if( !consdata0->upgraded )
13886  {
13887  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13888  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13889 
13890  (*nchgsides)++;
13891  }
13892  }
13893  }
13894  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13895  {
13896  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13897  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13898  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13899  SCIPdebugPrintCons(scip, cons1, NULL);
13900  SCIPdebugPrintCons(scip, cons0, NULL);
13901 
13902  /* check for infeasibility */
13903  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13904  {
13905  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13906  *cutoff = TRUE;
13907  break;
13908  }
13909 
13910  /* remove redundant left hand side */
13911  if( !SCIPisInfinity(scip, -consdata1->lhs) )
13912  {
13913  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13914  cons1isequality = FALSE;
13915  if( !consdata1->upgraded )
13916  {
13917  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13918  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13919 
13920  (*nchgsides)++;
13921  }
13922  }
13923  }
13924  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13925  {
13926  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13927  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13928  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13929  SCIPdebugPrintCons(scip, cons0, NULL);
13930  SCIPdebugPrintCons(scip, cons1, NULL);
13931 
13932  /* check for infeasibility */
13933  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13934  {
13935  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13936  *cutoff = TRUE;
13937  break;
13938  }
13939 
13940  /* remove redundant right hand side */
13941  if( !SCIPisInfinity(scip, consdata0->rhs) )
13942  {
13943  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13944  cons0rhs = consdata0->rhs;
13945  cons0isequality = FALSE;
13946  if( !consdata0->upgraded )
13947  {
13948  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13949  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13950 
13951  (*nchgsides)++;
13952  }
13953  }
13954  }
13955  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13956  {
13957  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13958  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13959  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13960  SCIPdebugPrintCons(scip, cons1, NULL);
13961  SCIPdebugPrintCons(scip, cons0, NULL);
13962 
13963  /* check for infeasibility */
13964  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13965  {
13966  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13967  *cutoff = TRUE;
13968  break;
13969  }
13970 
13971  /* remove redundant right hand side */
13972  if( !SCIPisInfinity(scip, consdata1->rhs) )
13973  {
13974  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13975  cons1isequality = FALSE;
13976  if( !consdata1->upgraded )
13977  {
13978  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13979  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13980 
13981  (*nchgsides)++;
13982  }
13983  }
13984  }
13985 
13986  /* check for now redundant constraints */
13987  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13988  {
13989  /* consdata0 became redundant */
13990  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13991  SCIP_CALL( SCIPdelCons(scip, cons0) );
13992  conss[chkind] = NULL;
13993  if( !consdata0->upgraded )
13994  {
13995  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13996  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13997 
13998  (*ndelconss)++;
13999  }
14000  continue;
14001  }
14002  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
14003  {
14004  /* consdata1 became redundant */
14005  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
14006  SCIP_CALL( SCIPdelCons(scip, cons1) );
14007  conss[c] = NULL;
14008  if( !consdata1->upgraded )
14009  {
14010  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14011  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
14012 
14013  (*ndelconss)++;
14014  }
14015  continue;
14016  }
14017 
14018  /* check, if we want to aggregate an (in)equality with an equality:
14019  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
14020  */
14021  if( tryaggregation )
14022  {
14023  SCIP_Bool aggregated;
14024 
14025  assert(consdata0->nvars == nvarscommon + nvars0minus1);
14026  assert(consdata1->nvars == nvarscommon + nvars1minus0);
14027 
14028  aggregated = FALSE;
14029  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
14030  {
14031  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
14032  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
14033  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
14034  nchgcoefs, &aggregated, cutoff) );
14035 
14036  if( *cutoff )
14037  break;
14038 
14039  /* update array of active constraints */
14040  if( aggregated )
14041  {
14042  assert(!SCIPconsIsActive(cons0));
14043  assert(SCIPconsIsActive(cons1));
14044  conss[chkind] = NULL;
14045  }
14046  }
14047  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
14048  {
14049  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
14050  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
14051  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
14052  nchgcoefs, &aggregated, cutoff) );
14053 
14054  if( *cutoff )
14055  break;
14056 
14057  /* update array of active constraints */
14058  if( aggregated )
14059  {
14060  assert(!SCIPconsIsActive(cons1));
14061  assert(SCIPconsIsActive(cons0));
14062  conss[c] = NULL;
14063  }
14064  }
14065  }
14066  }
14067 
14068  /* free temporary memory */
14069  SCIPfreeBufferArray(scip, &diffidx1minus0);
14070  SCIPfreeBufferArray(scip, &diffidx0minus1);
14071  SCIPfreeBufferArray(scip, &commonidx1);
14072  SCIPfreeBufferArray(scip, &commonidx0);
14073 
14074  return SCIP_OKAY;
14075 }
14076 
14077 /** do stuffing presolving on a single constraint */
14078 static
14080  SCIP* scip, /**< SCIP data structure */
14081  SCIP_CONS* cons, /**< linear constraint */
14082  SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14083  SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14084  * constraints using the cheapest variable? */
14085  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14086  int* nfixedvars, /**< pointer to count the total number of fixed variables */
14087  int* nchgbds /**< pointer to count the total number of tightened bounds */
14088  )
14089 {
14090  SCIP_CONSDATA* consdata;
14091  SCIP_Real* ratios;
14092  int* varpos;
14093  SCIP_Bool* swapped;
14094  SCIP_VAR** vars;
14095  SCIP_Real* vals;
14096  SCIP_VAR* var;
14097  SCIP_Real lb;
14099  SCIP_Real minactivity;
14100  SCIP_Real maxactivity;
14101  SCIP_Real maxcondactivity;
14102  SCIP_Real mincondactivity;
14103  SCIP_Real rhs;
14104  SCIP_Real val;
14105  SCIP_Real obj;
14106  SCIP_Real factor;
14107  SCIP_Bool minactisrelax;
14108  SCIP_Bool maxactisrelax;
14109  SCIP_Bool isminsettoinfinity;
14110  SCIP_Bool ismaxsettoinfinity;
14111  SCIP_Bool tryfixing;
14112  int nsingletons;
14113  int idx;
14114  int v;
14115  int nvars;
14116 
14117  assert(scip != NULL);
14118  assert(cons != NULL);
14119  assert(nfixedvars != NULL);
14120 
14121  consdata = SCIPconsGetData(cons);
14122 
14123  /* we only want to run for inequalities */
14124  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14125  return SCIP_OKAY;
14126 
14127  if( singlevarstuffing )
14128  {
14129  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
14130  &isminsettoinfinity, &ismaxsettoinfinity);
14131  }
14132  else
14133  {
14134  minactivity = SCIP_INVALID;
14135  maxactivity = SCIP_INVALID;
14136  isminsettoinfinity = FALSE;
14137  ismaxsettoinfinity = FALSE;
14138  }
14139 
14140  /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14141  * the new maxactivity is minus the old minactivity then
14142  */
14143  if( SCIPisInfinity(scip, consdata->rhs) )
14144  {
14145  rhs = -consdata->lhs;
14146  factor = -1.0;
14147  maxactivity = -minactivity;
14148  ismaxsettoinfinity = isminsettoinfinity;
14149  }
14150  else
14151  {
14152  assert(SCIPisInfinity(scip, -consdata->lhs));
14153  rhs = consdata->rhs;
14154  factor = 1.0;
14155  }
14156 
14157  nvars = consdata->nvars;
14158  vars = consdata->vars;
14159  vals = consdata->vals;
14160 
14161  /* check for continuous singletons */
14162  if( singletonstuffing )
14163  {
14164  for( v = 0; v < nvars; ++v )
14165  {
14166  var = vars[v];
14167 
14170  break;
14171  }
14172  }
14173  else
14174  /* we don't want to go into the next block */
14175  v = nvars;
14176 
14177  /* a singleton was found -> perform singleton variable stuffing */
14178  if( v < nvars )
14179  {
14180  assert(singletonstuffing);
14181 
14182  SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14183  SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14184  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14185 
14186  tryfixing = TRUE;
14187  nsingletons = 0;
14188  mincondactivity = 0.0;
14189  maxcondactivity = 0.0;
14190 
14191  for( v = 0; v < nvars; ++v )
14192  {
14193  var = vars[v];
14194  lb = SCIPvarGetLbGlobal(var);
14195  ub = SCIPvarGetUbGlobal(var);
14196  obj = SCIPvarGetObj(var);
14197  val = factor * vals[v];
14198 
14199  assert(!SCIPisZero(scip, val));
14200 
14201  /* the variable is a singleton and continuous */
14204  {
14205  if( SCIPisNegative(scip, obj) && val > 0 )
14206  {
14207  /* case 1: obj < 0 and coef > 0 */
14208  if( SCIPisInfinity(scip, -lb) )
14209  {
14210  tryfixing = FALSE;
14211  break;
14212  }
14213 
14214  maxcondactivity += val * lb;
14215  mincondactivity += val * lb;
14216  swapped[v] = FALSE;
14217  ratios[nsingletons] = obj / val;
14218  varpos[nsingletons] = v;
14219  nsingletons++;
14220  }
14221  else if( SCIPisPositive(scip, obj) && val < 0 )
14222  {
14223  /* case 2: obj > 0 and coef < 0 */
14224  if( SCIPisInfinity(scip, ub) )
14225  {
14226  tryfixing = FALSE;
14227  break;
14228  }
14229  /* multiply column by (-1) to become case 1.
14230  * now bounds are swapped: ub := -lb, lb := -ub
14231  */
14232 
14233  maxcondactivity += val * ub;
14234  mincondactivity += val * ub;
14235  swapped[v] = TRUE;
14236  ratios[nsingletons] = obj / val;
14237  varpos[nsingletons] = v;
14238  nsingletons++;
14239  }
14240  else if( val > 0 )
14241  {
14242  /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14243  * we only consider the lower bound for the constants
14244  */
14245  assert(!SCIPisNegative(scip, obj));
14246 
14247  if( SCIPisInfinity(scip, -lb) )
14248  {
14249  /* maybe unbounded */
14250  tryfixing = FALSE;
14251  break;
14252  }
14253 
14254  maxcondactivity += val * lb;
14255  mincondactivity += val * lb;
14256  }
14257  else
14258  {
14259  /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14260  * we only consider the upper bound for the constants
14261  */
14262  assert(!SCIPisPositive(scip, obj));
14263  assert(val < 0);
14264 
14265  if( SCIPisInfinity(scip, ub) )
14266  {
14267  /* maybe unbounded */
14268  tryfixing = FALSE;
14269  break;
14270  }
14271 
14272  maxcondactivity += val * ub;
14273  mincondactivity += val * ub;
14274  }
14275  }
14276  else
14277  {
14278  /* consider contribution of discrete variables, non-singleton
14279  * continuous variables and variables with more than one lock
14280  */
14281  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14282  {
14283  tryfixing = FALSE;
14284  break;
14285  }
14286 
14287  if( val > 0 )
14288  {
14289  maxcondactivity += val * ub;
14290  mincondactivity += val * lb;
14291  }
14292  else
14293  {
14294  maxcondactivity += val * lb;
14295  mincondactivity += val * ub;
14296  }
14297  }
14298  }
14299  if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14300  {
14301  SCIP_Real delta;
14302  SCIP_Bool tightened;
14303 #ifdef SCIP_DEBUG
14304  int oldnfixedvars = *nfixedvars;
14305  int oldnchgbds = *nchgbds;
14306 #endif
14307 
14308  SCIPsortRealInt(ratios, varpos, nsingletons);
14309 
14310  /* verify which singleton continuous variables can be fixed */
14311  for( v = 0; v < nsingletons; ++v )
14312  {
14313  idx = varpos[v];
14314  var = vars[idx];
14315  val = factor * vals[idx];
14316  lb = SCIPvarGetLbGlobal(var);
14317  ub = SCIPvarGetUbGlobal(var);
14318 
14319  assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14320  assert((val < 0) == swapped[idx]);
14321  val = REALABS(val);
14322 
14323  /* stop fixing if variable bounds are not finite */
14324  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14325  break;
14326 
14329  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14330 
14331  /* calculate the change in the row activities if this variable changes
14332  * its value from its worst to its best bound
14333  */
14334  if( swapped[idx] )
14335  delta = -(lb - ub) * val;
14336  else
14337  delta = (ub - lb) * val;
14338 
14339  assert(!SCIPisNegative(scip, delta));
14340 
14341  if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14342  {
14343  if( swapped[idx] )
14344  {
14345  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14346  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14347  }
14348  else
14349  {
14350  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14351  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14352  }
14353 
14354  if( *cutoff )
14355  break;
14356  if( tightened )
14357  {
14358  (*nfixedvars)++;
14359  }
14360  }
14361  /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14362  * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14363  * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14364  * troubles in case of large bounds.
14365  */
14366  else if( SCIPisLE(scip, rhs, mincondactivity) )
14367  {
14368  if( swapped[idx] )
14369  {
14370  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14371  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14372  }
14373  else
14374  {
14375  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14376  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14377  }
14378 
14379  if( *cutoff )
14380  break;
14381  if( tightened )
14382  {
14383  (*nfixedvars)++;
14384  }
14385  }
14386 
14387  maxcondactivity += delta;
14388  mincondactivity += delta;
14389  }
14390 
14391 #ifdef SCIP_DEBUG
14392  if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14393  {
14394  SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14395  }
14396 #endif
14397  }
14398 
14399  SCIPfreeBufferArray(scip, &swapped);
14400  SCIPfreeBufferArray(scip, &ratios);
14401  SCIPfreeBufferArray(scip, &varpos);
14402  }
14403 
14404  /* perform single-variable stuffing:
14405  * for a linear inequality
14406  * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14407  * with a_i > 0 and objective coefficients c_i < 0,
14408  * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14409  * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14410  * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14411  * is redundant.
14412  * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14413  * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14414  * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14415  * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14416  * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14417  * upper bound.
14418  * Note that the others variables may have downlocks from other constraints, which we do not need to care
14419  * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14420  * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14421  * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14422  * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14423  * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14424  * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14425  * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14426  * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14427  * c_k * ceil((maxactivity - rhs)/val) is still better than
14428  * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14429  * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14430  * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14431  * sign of coefficients in constraint and objective prevent the use of this method.
14432  */
14433  if( singlevarstuffing && !ismaxsettoinfinity )
14434  {
14435  SCIP_Real bestratio = -SCIPinfinity(scip);
14436  SCIP_Real secondbestratio = -SCIPinfinity(scip);
14437  SCIP_Real ratio;
14438  int bestindex = -1;
14439  int bestuplocks = 0;
14440  int bestdownlocks = 1;
14441  int downlocks;
14442  int uplocks;
14443  SCIPdebug( int oldnfixedvars = *nfixedvars; )
14444  SCIPdebug( int oldnchgbds = *nchgbds; )
14445 
14446  /* loop over all variables to identify the best and second-best ratio */
14447  for( v = 0; v < nvars; ++v )
14448  {
14449  var = vars[v];
14450  obj = SCIPvarGetObj(var);
14451  val = factor * vals[v];
14452 
14453  assert(!SCIPisZero(scip, val));
14454 
14455  ratio = obj / val;
14456 
14457  /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14458  if( !SCIPisNegative(scip, ratio) )
14459  {
14460  bestindex = -1;
14461  break;
14462  }
14463 
14464  if( val > 0 )
14465  {
14468  }
14469  else
14470  {
14471  downlocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
14473  }
14474 
14475  /* better ratio, update best candidate
14476  * @todo use some tolerance
14477  * @todo check size of domain and updated ratio for integer variables already?
14478  */
14479  if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14480  || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14481  && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
14482  {
14483  /* best index becomes second-best*/
14484  if( bestindex != -1 )
14485  {
14486  /* second-best index must not have more than 1 uplock */
14487  if( bestuplocks > 1 )
14488  {
14489  bestindex = -1;
14490  break;
14491  }
14492  else
14493  {
14494  secondbestratio = bestratio;
14495  }
14496  }
14497  bestdownlocks = downlocks;
14498  bestuplocks = uplocks;
14499  bestratio = ratio;
14500  bestindex = v;
14501 
14502  /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14503  * if it is not the best, it has too many uplocks -> not applicable
14504  */
14505  if( bestdownlocks > 0 && bestuplocks > 1 )
14506  {
14507  bestindex = -1;
14508  break;
14509  }
14510  }
14511  else
14512  {
14513  /* non-best index must not have more than 1 uplock */
14514  if( uplocks > 1 )
14515  {
14516  bestindex = -1;
14517  break;
14518  }
14519  /* update second-best ratio */
14520  if( ratio > secondbestratio )
14521  {
14522  secondbestratio = ratio;
14523  }
14524  }
14525  }
14526 
14527  /* check if we can apply single variable stuffing */
14528  if( bestindex != -1 && bestdownlocks == 0 )
14529  {
14530  SCIP_Bool tightened = FALSE;
14531  SCIP_Real bounddelta;
14532 
14533  var = vars[bestindex];
14534  obj = SCIPvarGetObj(var);
14535  val = factor * vals[bestindex];
14536  lb = SCIPvarGetLbGlobal(var);
14537  ub = SCIPvarGetUbGlobal(var);
14538  tryfixing = TRUE;
14539 
14540  if( val < 0 )
14541  {
14542  assert(!SCIPisNegative(scip, obj));
14543 
14544  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14545  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14546  {
14547  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14548  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14549  assert(SCIPisPositive(scip, activitydelta));
14550 
14551  tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14552 
14553  bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14554  assert(SCIPisPositive(scip, bounddelta));
14555  }
14556  else
14557  bounddelta = (maxactivity - rhs)/-val;
14558 
14559  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14560 
14561  if( tryfixing )
14562  {
14563  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
14564 
14565  if( SCIPisEQ(scip, lb + bounddelta, ub) )
14566  {
14567  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14568  SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14569  }
14570  else
14571  {
14572  SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14573  SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14574  }
14575  }
14576  }
14577  else
14578  {
14579  assert(!SCIPisPositive(scip, obj));
14580 
14581  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14582  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14583  {
14584  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14585  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14586  assert(SCIPisPositive(scip, activitydelta));
14587 
14588  tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14589 
14590  bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14591  assert(SCIPisPositive(scip, bounddelta));
14592  }
14593  else
14594  bounddelta = (maxactivity - rhs)/val;
14595 
14596  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14597 
14598  if( tryfixing )
14599  {
14600  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
14601 
14602  if( SCIPisEQ(scip, ub - bounddelta, lb) )
14603  {
14604  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14605  SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14606  }
14607  else
14608  {
14609  SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14610  SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14611  }
14612  }
14613  }
14614 
14615  if( *cutoff )
14616  return SCIP_OKAY;
14617  if( tightened )
14618  {
14619  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14620  ++(*nfixedvars);
14621  else
14622  ++(*nchgbds);
14623 
14624  SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14625  for( v = 0; v < nvars; ++v )
14626  {
14627  SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14628  SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14631  SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14632  }
14633  SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14634 
14635  for( v = 0; v < nvars; ++v )
14636  {
14637  if( v == bestindex )
14638  continue;
14639 
14640  if( factor * vals[v] < 0 )
14641  {
14642  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14643  SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14644  SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14645  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14646  }
14647  else
14648  {
14649  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14650  SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14651  SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14652  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14653  }
14654 
14655  if( *cutoff )
14656  return SCIP_OKAY;
14657  if( tightened )
14658  ++(*nfixedvars);
14659  }
14660  SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14661  }
14662  }
14663  }
14664 
14665  return SCIP_OKAY;
14666 }
14667 
14668 /** applies full dual presolving on variables that only appear in linear constraints */
14669 static
14671  SCIP* scip, /**< SCIP data structure */
14672  SCIP_CONS** conss, /**< constraint set */
14673  int nconss, /**< number of constraints */
14674  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14675  int* nchgbds /**< pointer to count the number of bound changes */
14676  )
14677 {
14678  SCIP_Real* redlb;
14679  SCIP_Real* redub;
14680  int* nlocksdown;
14681  int* nlocksup;
14682  SCIP_Bool* isimplint;
14683  SCIP_VAR** origvars;
14684  SCIP_VAR** vars;
14685  SCIP_VAR** conscontvars;
14686  int nvars;
14687  int nbinvars;
14688  int nintvars;
14689  int ncontvars;
14690  int v;
14691  int c;
14692 
14693  /* we calculate redundancy bounds with the following meaning:
14694  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14695  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14696  * then:
14697  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14698  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14699  */
14700 
14701  /* Additionally, we detect continuous variables that are implicitly integral.
14702  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14703  * and all constraints (including the bounds as trivial constraints) in which:
14704  * c_j > 0: the variable is down-locked,
14705  * c_j < 0: the variable is up-locked,
14706  * c_j = 0: the variable appears
14707  * have, apart from j, only integer variables with integral coefficients and integral sides.
14708  * This is because then, the value of the variable is either determined by one of its bounds or
14709  * by one of these constraints, and in all cases, the value of the variable is integral.
14710  */
14711 
14712  assert(scip != NULL);
14713  assert(nconss == 0 || conss != NULL);
14714  assert(nchgbds != NULL);
14715  assert(!SCIPinProbing(scip));
14716 
14717  /* get active variables */
14718  nvars = SCIPgetNVars(scip);
14719  origvars = SCIPgetVars(scip);
14720 
14721  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14722  nbinvars = SCIPgetNBinVars(scip);
14723  if( nbinvars == nvars )
14724  return SCIP_OKAY;
14725 
14726  /* get number of continuous variables */
14727  ncontvars = SCIPgetNContVars(scip);
14728  nintvars = nvars - ncontvars;
14729 
14730  /* copy the variable array since this array might change during the curse of this algorithm */
14731  nvars = nvars - nbinvars;
14732  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14733 
14734  /* allocate temporary memory */
14735  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14736  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14737  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14738  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14739  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14740  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14741 
14742  /* initialize redundancy bounds */
14743  for( v = 0; v < nvars; ++v )
14744  {
14745  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14746  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14747  redub[v] = SCIPvarGetUbGlobal(vars[v]);
14748  }
14749  BMSclearMemoryArray(nlocksdown, nvars);
14750  BMSclearMemoryArray(nlocksup, nvars);
14751 
14752  /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14753  * We better not use SCIPisFeasIntegral() in these checks.
14754  */
14755  for( v = 0; v < ncontvars; v++ )
14756  {
14757  SCIP_VAR* var;
14758  SCIP_Real obj;
14759  SCIP_Real lb;
14760  SCIP_Real ub;
14761 
14762  var = vars[v + nintvars - nbinvars];
14763  lb = SCIPvarGetLbGlobal(var);
14764  ub = SCIPvarGetUbGlobal(var);
14765 
14766  obj = SCIPvarGetObj(var);
14767  if( SCIPisZero(scip, obj) )
14768  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14769  else
14770  {
14771  if( SCIPisPositive(scip, obj) )
14772  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14773  else
14774  {
14775  assert(SCIPisNegative(scip, obj));
14776  isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14777  }
14778  }
14779  }
14780 
14781  /* scan all constraints */
14782  for( c = 0; c < nconss; ++c )
14783  {
14784  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14785  * part of checked disjunctions)
14786  */
14787  if( SCIPconsIsLocked(conss[c]) )
14788  {
14789  SCIP_CONSDATA* consdata;
14790  SCIP_Bool lhsexists;
14791  SCIP_Bool rhsexists;
14792  SCIP_Bool hasimpliedpotential;
14793  SCIP_Bool integralcoefs;
14794  int nlockspos;
14795  int contvarpos;
14796  int nconscontvars;
14797  int i;
14798 
14799  consdata = SCIPconsGetData(conss[c]);
14800  assert(consdata != NULL);
14801 
14802  /* get number of times the constraint was locked */
14803  nlockspos = SCIPconsGetNLocksPos(conss[c]);
14804 
14805  /* we do not want to include constraints with locked negation (this would be too weird) */
14806  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14807  {
14808  /* mark all continuous variables as not being implicit integral */
14809  for( i = 0; i < consdata->nvars; ++i )
14810  {
14811  SCIP_VAR* var;
14812 
14813  var = consdata->vars[i];
14815  {
14816  int contv;
14817  contv = SCIPvarGetProbindex(var) - nintvars;
14818  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14819  isimplint[contv] = FALSE;
14820  }
14821  }
14822  continue;
14823  }
14824 
14825  /* check for existing sides */
14826  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14827  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14828 
14829  /* count locks and update redundancy bounds */
14830  contvarpos = -1;
14831  nconscontvars = 0;
14832  hasimpliedpotential = FALSE;
14833  integralcoefs = !SCIPconsIsModifiable(conss[c]);
14834 
14835  for( i = 0; i < consdata->nvars; ++i )
14836  {
14837  SCIP_VAR* var;
14838  SCIP_Real val;
14839  SCIP_Real minresactivity;
14840  SCIP_Real maxresactivity;
14841  SCIP_Real newredlb;
14842  SCIP_Real newredub;
14843  SCIP_Bool minisrelax;
14844  SCIP_Bool maxisrelax;
14845  SCIP_Bool isminsettoinfinity;
14846  SCIP_Bool ismaxsettoinfinity;
14847  int arrayindex;
14848 
14849  var = consdata->vars[i];
14850  val = consdata->vals[i];
14851 
14852  /* check if still all integer variables have integral coefficients */
14853  if( SCIPvarIsIntegral(var) )
14854  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14855 
14856  /* we do not need to process binary variables */
14857  if( SCIPvarIsBinary(var) )
14858  continue;
14859 
14860  if( SCIPconsIsModifiable(conss[c]) )
14861  {
14862  minresactivity = -SCIPinfinity(scip);
14863  maxresactivity = SCIPinfinity(scip);
14864  isminsettoinfinity = TRUE;
14865  ismaxsettoinfinity = TRUE;
14866  }
14867  else
14868  {
14869  /* calculate residual activity bounds if variable would be fixed to zero */
14870  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14871  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
14872 
14873  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14874  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14875  * This is needed, because we do not want to rely on relaxed finite resactivities.
14876  */
14877  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
14878 
14879  /* check minresactivity for reliability */
14880  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14881  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14882 
14883  /* check maxresactivity for reliability */
14884  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14885  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14886  }
14887 
14888  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14889 
14890  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14891 
14892  newredlb = redlb[arrayindex];
14893  newredub = redub[arrayindex];
14894  if( val > 0.0 )
14895  {
14896  if( lhsexists )
14897  {
14898  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14899  nlocksdown[arrayindex] += nlockspos;
14900  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14901  }
14902  if( rhsexists )
14903  {
14904  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14905  nlocksup[arrayindex] += nlockspos;
14906  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14907  }
14908  }
14909  else
14910  {
14911  if( lhsexists )
14912  {
14913  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14914  nlocksup[arrayindex] += nlockspos;
14915  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14916  }
14917  if( rhsexists )
14918  {
14919  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14920  nlocksdown[arrayindex] += nlockspos;
14921  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14922  }
14923  }
14924 
14925  /* if the variable is integer, we have to round the value to the next integral value */
14926  if( SCIPvarIsIntegral(var) )
14927  {
14928  if( !SCIPisInfinity(scip, newredlb) )
14929  newredlb = SCIPceil(scip, newredlb);
14930  if( !SCIPisInfinity(scip, -newredub) )
14931  newredub = SCIPfloor(scip, newredub);
14932  }
14933 
14934  /* update redundancy bounds */
14935  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14936  redub[arrayindex] = MIN(redub[arrayindex], newredub);
14937 
14938  /* collect the continuous variables of the constraint */
14940  {
14941  int contv;
14942 
14943  assert(nconscontvars < ncontvars);
14944  contvarpos = i;
14945  conscontvars[nconscontvars] = var;
14946  nconscontvars++;
14947 
14948  contv = SCIPvarGetProbindex(var) - nintvars;
14949  assert(0 <= contv && contv < ncontvars);
14950  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14951  }
14952  }
14953 
14954  /* update implicit integer status of continuous variables */
14955  if( hasimpliedpotential )
14956  {
14957  if( nconscontvars > 1 || !integralcoefs )
14958  {
14959  /* there is more than one continuous variable or the integer variables have fractional coefficients:
14960  * none of the continuous variables is implicit integer
14961  */
14962  for( i = 0; i < nconscontvars; i++ )
14963  {
14964  int contv;
14965  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14966  assert(0 <= contv && contv < ncontvars);
14967  isimplint[contv] = FALSE;
14968  }
14969  }
14970  else
14971  {
14972  SCIP_VAR* var;
14973  SCIP_Real val;
14974  SCIP_Real absval;
14975  int contv;
14976 
14977  /* there is exactly one continuous variable and the integer variables have integral coefficients:
14978  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14979  * side(s) of the constraint is integral
14980  */
14981  assert(nconscontvars == 1);
14982  assert(0 <= contvarpos && contvarpos < consdata->nvars);
14983  var = consdata->vars[contvarpos];
14984  val = consdata->vals[contvarpos];
14985  contv = SCIPvarGetProbindex(var) - nintvars;
14986  assert(0 <= contv && contv < ncontvars);
14987  assert(isimplint[contv]);
14988 
14989  absval = REALABS(val);
14990  if( !SCIPisEQ(scip, absval, 1.0) )
14991  isimplint[contv] = FALSE;
14992  else
14993  {
14994  SCIP_Real obj;
14995 
14996  obj = SCIPvarGetObj(var);
14997  if( obj * val >= 0.0 && lhsexists )
14998  {
14999  /* the variable may be blocked by the constraint's left hand side */
15000  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
15001  }
15002  if( obj * val <= 0.0 && rhsexists )
15003  {
15004  /* the variable may be blocked by the constraint's left hand side */
15005  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
15006  }
15007  }
15008  }
15009  }
15010  }
15011  }
15012 
15013  /* check if any bounds can be tightened due to optimality */
15014  for( v = 0; v < nvars; ++v )
15015  {
15016  SCIP_VAR* var;
15017  SCIP_Real obj;
15018  SCIP_Bool infeasible;
15019  SCIP_Bool tightened;
15020 
15021  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
15022  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15023  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15024 
15025  var = vars[v];
15026  obj = SCIPvarGetObj(var);
15027  if( !SCIPisPositive(scip, -obj) )
15028  {
15029  /* making the variable as small as possible does not increase the objective:
15030  * check if all down locks of the variables are due to linear constraints;
15031  * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
15032  * constraints redundant is huge, we better do nothing for numerical reasons
15033  */
15034  if( ( SCIPisPositive(scip, obj) || SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) || !SCIPisInfinity(scip, -SCIPvarGetLbGlobal(var)) )
15035  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15036  && !SCIPisHugeValue(scip, -redlb[v])
15037  && redlb[v] < SCIPvarGetUbGlobal(var) )
15038  {
15039  SCIP_Real ub;
15040 
15041  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
15042  * -> tighten upper bound to x_v <= redlb[v]
15043  */
15044  SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
15046  redlb[v]);
15047  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
15048  assert(!infeasible);
15049 
15050  ub = SCIPvarGetUbGlobal(var);
15051  redub[v] = MIN(redub[v], ub);
15052  if( tightened )
15053  (*nchgbds)++;
15054  }
15055  }
15056  if( !SCIPisPositive(scip, obj) )
15057  {
15058  /* making the variable as large as possible does not increase the objective:
15059  * check if all up locks of the variables are due to linear constraints;
15060  * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
15061  * constraints redundant is huge, we better do nothing for numerical reasons
15062  */
15063  if( ( SCIPisPositive(scip, -obj) || SCIPisPositive(scip, -SCIPvarGetLbGlobal(var)) || !SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)) )
15064  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
15065  && !SCIPisHugeValue(scip, redub[v])
15066  && redub[v] > SCIPvarGetLbGlobal(var) )
15067  {
15068  SCIP_Real lb;
15069 
15070  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
15071  * -> tighten lower bound to x_v >= redub[v]
15072  */
15073  SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
15075  redub[v]);
15076  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15077  assert(!infeasible);
15078 
15079  lb = SCIPvarGetLbGlobal(var);
15080  redlb[v] = MAX(redlb[v], lb);
15081  if( tightened )
15082  (*nchgbds)++;
15083  }
15084  }
15085  }
15086 
15087  /* upgrade continuous variables to implicit integers */
15088  for( v = nintvars - nbinvars; v < nvars; ++v )
15089  {
15090  SCIP_VAR* var;
15091  SCIP_Bool infeasible;
15092 
15093  var = vars[v];
15094  assert(var != NULL);
15095 
15096  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
15097  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15098  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15099  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15100 
15101  /* we can only conclude implicit integrality if the variable appears in no other constraint */
15102  if( isimplint[v - nintvars + nbinvars]
15103  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15104  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15105  {
15106  /* since we locally copied the variable array we can change the variable type immediately */
15107  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15108 
15109  if( infeasible )
15110  {
15111  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15112  *cutoff = TRUE;
15113 
15114  break;
15115  }
15116 
15117  SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15119  }
15120  }
15121 
15122  /* free temporary memory */
15123  SCIPfreeBufferArray(scip, &conscontvars);
15124  SCIPfreeBufferArray(scip, &isimplint);
15125  SCIPfreeBufferArray(scip, &nlocksup);
15126  SCIPfreeBufferArray(scip, &nlocksdown);
15127  SCIPfreeBufferArray(scip, &redub);
15128  SCIPfreeBufferArray(scip, &redlb);
15129 
15130  SCIPfreeBufferArray(scip, &vars);
15131 
15132  return SCIP_OKAY;
15133 }
15134 
15135 /** helper function to enforce constraints */
15136 static
15138  SCIP* scip, /**< SCIP data structure */
15139  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15140  SCIP_CONS** conss, /**< constraints to process */
15141  int nconss, /**< number of constraints */
15142  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15143  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15144  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15145  )
15146 {
15147  SCIP_CONSHDLRDATA* conshdlrdata;
15148  SCIP_Bool checkrelmaxabs;
15149  SCIP_Bool violated;
15150  SCIP_Bool cutoff = FALSE;
15151  int c;
15152 
15153  assert(scip != NULL);
15154  assert(conshdlr != NULL);
15155  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15156  assert(result != NULL);
15157 
15158  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15159  assert(conshdlrdata != NULL);
15160 
15161  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15162 
15163  SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15164 
15165  /* check for violated constraints
15166  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15167  */
15168  *result = SCIP_FEASIBLE;
15169 
15170  /* check all useful linear constraints for feasibility */
15171  for( c = 0; c < nusefulconss; ++c )
15172  {
15173  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15174 
15175  if( violated )
15176  {
15177  /* insert LP row as cut */
15178  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15179  if ( cutoff )
15180  *result = SCIP_CUTOFF;
15181  else
15182  *result = SCIP_SEPARATED;
15183  }
15184  }
15185 
15186  /* check all obsolete linear constraints for feasibility */
15187  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15188  {
15189  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15190 
15191  if( violated )
15192  {
15193  /* insert LP row as cut */
15194  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15195  if ( cutoff )
15196  *result = SCIP_CUTOFF;
15197  else
15198  *result = SCIP_SEPARATED;
15199  }
15200  }
15201 
15202  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15203 
15204  return SCIP_OKAY;
15205 }
15206 
15207 /** adds symmetry information of constraint to a symmetry detection graph */
15208 static
15210  SCIP* scip, /**< SCIP pointer */
15211  SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15212  SCIP_CONS* cons, /**< constraint */
15213  SYM_GRAPH* graph, /**< symmetry detection graph */
15214  SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15215  )
15216 {
15217  SCIP_CONSDATA* consdata;
15218  SCIP_VAR** vars;
15219  SCIP_Real* vals;
15220  SCIP_Real constant = 0.0;
15221  SCIP_Real lhs;
15222  SCIP_Real rhs;
15223  int nlocvars;
15224  int nvars;
15225  int i;
15226 
15227  assert(scip != NULL);
15228  assert(cons != NULL);
15229  assert(graph != NULL);
15230  assert(success != NULL);
15231 
15232  consdata = SCIPconsGetData(cons);
15233  assert(consdata != NULL);
15234 
15235  /* get active variables of the constraint */
15236  nvars = SCIPgetNVars(scip);
15237  nlocvars = consdata->nvars;
15238 
15239  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
15240  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
15241 
15242  for( i = 0; i < nlocvars; ++i )
15243  {
15244  vars[i] = consdata->vars[i];
15245  vals[i] = consdata->vals[i];
15246  }
15247 
15248  SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15249  lhs = consdata->lhs - constant;
15250  rhs = consdata->rhs - constant;
15251 
15252  /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15253  * of the same constraint are rated as equal
15254  */
15255  if ( SCIPisInfinity(scip, rhs) )
15256  {
15257  SCIP_Real tmp;
15258  assert(!SCIPisInfinity(scip, -lhs));
15259 
15260  for( i = 0; i < nlocvars; ++i )
15261  vals[i] *= -1;
15262  tmp = rhs;
15263  rhs = -lhs;
15264  lhs = -tmp;
15265  }
15266 
15267  SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
15268  cons, lhs, rhs, success) );
15269 
15270  SCIPfreeBufferArray(scip, &vals);
15271  SCIPfreeBufferArray(scip, &vars);
15272 
15273  return SCIP_OKAY;
15274 }
15275 
15276 /*
15277  * Callback methods of constraint handler
15278  */
15279 
15280 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
15281 static
15282 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15283 { /*lint --e{715}*/
15284  assert(scip != NULL);
15285  assert(conshdlr != NULL);
15286  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15287 
15288  /* call inclusion method of constraint handler */
15290 
15291  *valid = TRUE;
15292 
15293  return SCIP_OKAY;
15294 }
15295 
15296 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15297 static
15298 SCIP_DECL_CONSFREE(consFreeLinear)
15299 { /*lint --e{715}*/
15300  SCIP_CONSHDLRDATA* conshdlrdata;
15302  assert(scip != NULL);
15303  assert(conshdlr != NULL);
15304  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15305 
15306  /* free constraint handler data */
15307  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15308  assert(conshdlrdata != NULL);
15309 
15310  conshdlrdataFree(scip, &conshdlrdata);
15311 
15312  SCIPconshdlrSetData(conshdlr, NULL);
15313 
15314  return SCIP_OKAY;
15315 }
15316 
15318 /** initialization method of constraint handler (called after problem was transformed) */
15319 static
15320 SCIP_DECL_CONSINIT(consInitLinear)
15321 {
15322  SCIP_CONSHDLRDATA* conshdlrdata;
15323  int c;
15324 
15325  assert(scip != NULL);
15326 
15327  /* check for event handler */
15328  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15329  assert(conshdlrdata != NULL);
15330  assert(conshdlrdata->eventhdlr != NULL);
15331  assert(nconss == 0 || conss != NULL);
15332 
15333  conshdlrdata->naddconss = 0;
15334 
15335  /* catch events for the constraints */
15336  for( c = 0; c < nconss; ++c )
15337  {
15338  /* catch all events */
15339  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15340  }
15341 
15342  return SCIP_OKAY;
15343 }
15344 
15345 
15346 /** deinitialization method of constraint handler (called before transformed problem is freed) */
15347 static
15348 SCIP_DECL_CONSEXIT(consExitLinear)
15349 {
15350  SCIP_CONSHDLRDATA* conshdlrdata;
15351  int c;
15352 
15353  assert(scip != NULL);
15354 
15355  /* check for event handler */
15356  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15357  assert(conshdlrdata != NULL);
15358  assert(conshdlrdata->eventhdlr != NULL);
15359 
15360  /* drop events for the constraints */
15361  for( c = nconss - 1; c >= 0; --c )
15362  {
15363  SCIP_CONSDATA* consdata;
15364 
15365  consdata = SCIPconsGetData(conss[c]);
15366  assert(consdata != NULL);
15368  if( consdata->eventdata != NULL )
15369  {
15370  /* drop all events */
15371  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15372  assert(consdata->eventdata == NULL);
15373  }
15374  }
15375 
15376  return SCIP_OKAY;
15377 }
15378 
15379 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15380 static
15382  SCIP* scip, /**< SCIP data structure */
15383  SCIP_Real lhs, /**< left hand side */
15384  SCIP_Real rhs /**< right hand side */
15385  )
15386 {
15387  assert(scip != NULL);
15388 
15389  return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15390 }
15391 
15392 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15393 static
15395  SCIP* scip, /**< SCIP data structure */
15396  SCIP_Real x /**< value */
15397  )
15398 {
15399  assert(scip != NULL);
15401  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15402 }
15403 
15404 /** performs linear constraint type classification as used for MIPLIB
15405  *
15406  * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15407  *
15408  * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15409  * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15410  * Similarly, if specialized constraints were created through the API, these are currently not present.
15411  */
15413  SCIP* scip, /**< SCIP data structure */
15414  SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15415  )
15416 {
15417  int c;
15418  SCIP_CONSHDLR* conshdlr;
15419  SCIP_CONS** conss;
15420  int nconss;
15421 
15422  assert(scip != NULL);
15423  assert(linconsstats != NULL);
15424  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15425  assert(conshdlr != NULL);
15426 
15427  if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
15428  {
15429  conss = SCIPgetConss(scip);
15430  nconss = SCIPgetNConss(scip);
15431  }
15432  else
15433  {
15434  conss = SCIPconshdlrGetConss(conshdlr);
15435  nconss = SCIPconshdlrGetNConss(conshdlr);
15436  }
15437 
15438  /* reset linear constraint type classification */
15439  SCIPlinConsStatsReset(linconsstats);
15440 
15441  /* loop through all constraints */
15442  for( c = 0; c < nconss; c++ )
15443  {
15444  SCIP_CONS* cons;
15445  SCIP_CONSDATA* consdata;
15446  SCIP_Real lhs;
15447  SCIP_Real rhs;
15448  int i;
15449 
15450  /* get constraint */
15451  cons = conss[c];
15452  assert(cons != NULL);
15453 
15454  /* skip constraints that are not handled by the constraint handler */
15455  if( SCIPconsGetHdlr(cons) != conshdlr )
15456  continue;
15457 
15458  /* get constraint data */
15459  consdata = SCIPconsGetData(cons);
15460  assert(consdata != NULL);
15461  rhs = consdata->rhs;
15462  lhs = consdata->lhs;
15463 
15464  /* merge multiples and delete variables with zero coefficient */
15465  SCIP_CALL( mergeMultiples(scip, cons) );
15466  for( i = 0; i < consdata->nvars; i++ )
15467  {
15468  assert(!SCIPisZero(scip, consdata->vals[i]));
15469  }
15470 
15471  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15472  if( consdata->nvars == 0 )
15473  {
15474  SCIPdebugMsg(scip, "classified as EMPTY: ");
15475  SCIPdebugPrintCons(scip, cons, NULL);
15477 
15478  continue;
15479  }
15480 
15481  /* is constraint of type SCIP_CONSTYPE_FREE? */
15482  if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15483  {
15484  SCIPdebugMsg(scip, "classified as FREE: ");
15485  SCIPdebugPrintCons(scip, cons, NULL);
15487 
15488  continue;
15489  }
15490 
15491  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15492  if( consdata->nvars == 1 )
15493  {
15494  SCIPdebugMsg(scip, "classified as SINGLETON: ");
15495  SCIPdebugPrintCons(scip, cons, NULL);
15496  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15497 
15498  continue;
15499  }
15500 
15501  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15502  if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15503  {
15504  SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15505  SCIPdebugPrintCons(scip, cons, NULL);
15507 
15508  continue;
15509  }
15510 
15511  /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15512  if( consdata->nvars == 2 )
15513  {
15514  SCIP_LINCONSTYPE constype;
15515 
15516  /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15517  if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15518  && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15519  {
15520  constype = SCIP_LINCONSTYPE_PRECEDENCE;
15521  SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15522  }
15523  else
15524  {
15525  constype = SCIP_LINCONSTYPE_VARBOUND;
15526  SCIPdebugMsg(scip, "classified as VARBOUND: ");
15527  }
15528  SCIPdebugPrintCons(scip, cons, NULL);
15529 
15530  SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15531 
15532  continue;
15533  }
15534 
15535  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15536  {
15537  SCIP_Real scale;
15538  SCIP_Real b;
15539  SCIP_Bool unmatched;
15540  int nnegbinvars;
15541 
15542  unmatched = FALSE;
15543  nnegbinvars = 0;
15544 
15545  scale = REALABS(consdata->vals[0]);
15546 
15547  /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15548  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15549  {
15550  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15551  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15552  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15553  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15554 
15555  if( consdata->vals[i] < 0.0 )
15556  nnegbinvars++;
15557  }
15558 
15559  if( !unmatched )
15560  {
15561  if( SCIPisEQ(scip, lhs, rhs) )
15562  {
15563  b = rhs/scale + nnegbinvars;
15564  if( SCIPisEQ(scip, 1.0, b) )
15565  {
15566  SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15567  SCIPdebugPrintCons(scip, cons, NULL);
15569 
15570  continue;
15571  }
15572  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15573  {
15574  SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15575  SCIPdebugPrintCons(scip, cons, NULL);
15577 
15578  continue;
15579  }
15580  }
15581 
15582  /* compute right hand side divided by scale */
15583  if( !SCIPisInfinity(scip, rhs) )
15584  b = rhs/scale + nnegbinvars;
15585  else
15586  b = SCIPinfinity(scip);
15587 
15588  if( SCIPisEQ(scip, 1.0, b) )
15589  {
15590  SCIPdebugMsg(scip, "classified as SETPACKING: ");
15591  SCIPdebugPrintCons(scip, cons, NULL);
15593 
15594  /* relax right hand side to prevent further classifications */
15595  rhs = SCIPinfinity(scip);
15596  }
15597  else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15598  {
15599  SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15600  SCIPdebugPrintCons(scip, cons, NULL);
15601 
15603 
15604  /* relax right hand side to prevent further classifications */
15605  rhs = SCIPinfinity(scip);
15606  }
15607 
15608  if( !SCIPisInfinity(scip, lhs) )
15609  b = lhs/scale + nnegbinvars;
15610  else
15611  b = SCIPinfinity(scip);
15612 
15613  if( SCIPisEQ(scip, 1.0, b) )
15614  {
15615  SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15616  SCIPdebugPrintCons(scip, cons, NULL);
15618 
15619  /* relax left hand side to prevent further classifications */
15620  lhs = -SCIPinfinity(scip);
15621  }
15622 
15623  /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15624  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15625  continue;
15626  }
15627  }
15628 
15629  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15630  /* @todo If coefficients or rhs are not integral, we currently do not check
15631  * if the constraint could be scaled (finitely), such that they are.
15632  */
15633  {
15634  SCIP_Real b;
15635  SCIP_Bool unmatched;
15636 
15637  b = rhs;
15638  unmatched = FALSE;
15639  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15640  {
15641  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15642  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15643  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15644  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15645 
15646  if( SCIPisNegative(scip, consdata->vals[i]) )
15647  b -= consdata->vals[i];
15648  }
15649  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15650 
15651  if( !unmatched )
15652  {
15653  if( SCIPisEQ(scip, lhs, rhs) )
15654  {
15655  SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15656  SCIPdebugPrintCons(scip, cons, NULL);
15657 
15659 
15660  continue;
15661  }
15662  else
15663  {
15664  SCIP_Bool matched;
15665 
15666  matched = FALSE;
15667  for( i = 0; i < consdata->nvars && !matched; i++ )
15668  {
15669  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15670  }
15671 
15672  SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15673  SCIPdebugPrintCons(scip, cons, NULL);
15675  }
15676 
15677  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15678  if( SCIPisInfinity(scip, -lhs) )
15679  continue;
15680  else
15681  rhs = SCIPinfinity(scip);
15682  }
15683  }
15684 
15685  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15686  {
15687  SCIP_Real b;
15688  SCIP_Bool unmatched;
15689 
15690  unmatched = FALSE;
15691 
15692  b = rhs;
15693  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15694 
15695  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15696  {
15697  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15698  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15699  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15700  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15701  }
15702 
15703  if( !unmatched )
15704  {
15705  SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15706  SCIPdebugPrintCons(scip, cons, NULL);
15708 
15709  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15710  if( SCIPisInfinity(scip, -lhs) )
15711  continue;
15712  else
15713  rhs = SCIPinfinity(scip);
15714  }
15715  }
15716 
15717  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15718  {
15719  SCIP_Bool unmatched;
15720 
15721  unmatched = FALSE;
15722  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15723  {
15724  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15725  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15726  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15727  unmatched = TRUE;
15728  }
15729 
15730  if( !unmatched )
15731  {
15732  SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15733  SCIPdebugPrintCons(scip, cons, NULL);
15734  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15735 
15736  continue;
15737  }
15738  }
15739 
15740  /* no special structure detected */
15741  SCIPdebugMsg(scip, "classified as GENERAL: ");
15742  SCIPdebugPrintCons(scip, cons, NULL);
15743  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15744  }
15745 
15746  return SCIP_OKAY;
15747 }
15748 
15749 
15750 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15751 static
15752 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15753 { /*lint --e{715}*/
15754  int c;
15755 #ifdef SCIP_STATISTIC
15756  SCIP_CONSHDLRDATA* conshdlrdata;
15757  int ngoodconss;
15758  int nallconss;
15759 #endif
15760 
15761  /* delete all linear constraints that were upgraded to a more specific constraint type;
15762  * make sure, only active variables remain in the remaining constraints
15763  */
15764  assert(scip != NULL);
15765 
15766 #ifdef SCIP_STATISTIC
15767  /* count number of well behaved linear constraints */
15768  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15769  assert(conshdlrdata != NULL);
15770 
15771  ngoodconss = 0;
15772  nallconss = 0;
15773 
15774  for( c = 0; c < nconss; ++c )
15775  {
15776  SCIP_CONSDATA* consdata;
15777 
15778  if( SCIPconsIsDeleted(conss[c]) )
15779  continue;
15780 
15781  consdata = SCIPconsGetData(conss[c]);
15782  assert(consdata != NULL);
15783 
15784  if( consdata->upgraded )
15785  continue;
15786 
15787  nallconss++;
15788 
15789  consdataRecomputeMaxActivityDelta(scip, consdata);
15790 
15791  if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15792  ngoodconss++;
15793  }
15794  if( nallconss )
15795  {
15796  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15797  }
15798 #endif
15799 
15800  for( c = 0; c < nconss; ++c )
15801  {
15802  SCIP_CONSDATA* consdata;
15803 
15804  if( SCIPconsIsDeleted(conss[c]) )
15805  continue;
15806 
15807  consdata = SCIPconsGetData(conss[c]);
15808  assert(consdata != NULL);
15809 
15810  if( consdata->upgraded )
15811  {
15812  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15813  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15814  */
15815  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15816  }
15817  else
15818  {
15819  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15820  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15821  }
15822  }
15823 
15824  return SCIP_OKAY;
15825 }
15826 
15827 /** solving process initialization method of constraint handler */
15828 static
15829 SCIP_DECL_CONSINITSOL(consInitsolLinear)
15830 { /*lint --e{715}*/
15831  /* add nlrow representation to NLP, if NLP had been constructed */
15832  if( SCIPisNLPConstructed(scip) )
15833  {
15834  int c;
15835  for( c = 0; c < nconss; ++c )
15836  {
15837  SCIP_CALL( addNlrow(scip, conss[c]) );
15838  }
15839  }
15840 
15841  return SCIP_OKAY;
15842 }
15843 
15844 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15845 static
15846 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15847 { /*lint --e{715}*/
15848  int c;
15849 
15850  assert(scip != NULL);
15851 
15852  /* release the rows and nlrows of all constraints */
15853  for( c = 0; c < nconss; ++c )
15854  {
15855  SCIP_CONSDATA* consdata;
15856 
15857  consdata = SCIPconsGetData(conss[c]);
15858  assert(consdata != NULL);
15859 
15860  if( consdata->row != NULL )
15861  {
15862  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15863  }
15864 
15865  if( consdata->nlrow != NULL )
15866  {
15867  SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15868  }
15869  }
15870 
15871  /* if this is a restart, convert cutpool rows into linear constraints */
15872  if( restart )
15873  {
15874  int ncutsadded;
15875 
15876  ncutsadded = 0;
15877 
15878  /* create out of all active cuts in cutpool linear constraints */
15879  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15880 
15881  if( ncutsadded > 0 )
15882  {
15884  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15885  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15886  * line correctly
15887  */
15889  }
15890  }
15891 
15892  return SCIP_OKAY;
15893 }
15894 
15895 
15896 /** constraint activation notification method of constraint handler */
15897 static
15898 SCIP_DECL_CONSACTIVE(consActiveLinear)
15899 { /*lint --e{715}*/
15900  assert(cons != NULL);
15901 
15902  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisNLPConstructed(scip) )
15903  {
15904  SCIP_CALL( addNlrow(scip, cons) );
15905  }
15906 
15907  return SCIP_OKAY;
15908 }
15909 
15910 /** constraint deactivation notification method of constraint handler */
15911 static
15912 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15913 { /*lint --e{715}*/
15914  SCIP_CONSDATA* consdata;
15915 
15916  assert(scip != NULL);
15917  assert(conshdlr != NULL);
15918  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15919  assert(cons != NULL );
15920 
15921  /* get constraint data */
15922  consdata = SCIPconsGetData(cons);
15923  assert(consdata != NULL);
15924 
15925  if( SCIPconsIsDeleted(cons) )
15926  {
15927  SCIP_CONSHDLRDATA* conshdlrdata;
15928 
15929  /* check for event handler */
15930  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15931  assert(conshdlrdata != NULL);
15932  assert(conshdlrdata->eventhdlr != NULL);
15933 
15934  /* free event data */
15935  if( consdata->eventdata != NULL )
15936  {
15937  /* drop bound change events of variables */
15938  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15939  }
15940  assert(consdata->eventdata == NULL);
15941  }
15942 
15943  /* remove row from NLP, if still in solving
15944  * if we are in exitsolve, the whole NLP will be freed anyway
15945  */
15946  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15947  {
15948  SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15949  }
15950 
15951  return SCIP_OKAY;
15952 }
15953 
15954 
15955 /** frees specific constraint data */
15956 static
15957 SCIP_DECL_CONSDELETE(consDeleteLinear)
15958 { /*lint --e{715}*/
15959  assert(scip != NULL);
15960  assert(conshdlr != NULL);
15961  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15962 
15963  if( (*consdata)->eventdata != NULL )
15964  {
15965  SCIP_CONSHDLRDATA* conshdlrdata;
15966 
15967  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15968  assert(conshdlrdata != NULL);
15969 
15970  /* drop all events */
15971  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15972  assert((*consdata)->eventdata == NULL);
15973  }
15974 
15975  /* free linear constraint */
15976  SCIP_CALL( consdataFree(scip, consdata) );
15977 
15978  return SCIP_OKAY;
15979 }
15980 
15981 
15982 /** transforms constraint data into data belonging to the transformed problem */
15983 static
15984 SCIP_DECL_CONSTRANS(consTransLinear)
15985 { /*lint --e{715}*/
15986  SCIP_CONSDATA* sourcedata;
15987  SCIP_CONSDATA* targetdata;
15988 
15989  /*debugMsg(scip, "Trans method of linear constraints\n");*/
15990 
15991  assert(scip != NULL);
15992  assert(conshdlr != NULL);
15993  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15994  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
15995  assert(sourcecons != NULL);
15996  assert(targetcons != NULL);
15997 
15998  sourcedata = SCIPconsGetData(sourcecons);
15999  assert(sourcedata != NULL);
16000  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
16001 
16002  /* create linear constraint data for target constraint */
16003  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
16004 
16005 #ifndef NDEBUG
16006  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
16007  if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
16008  {
16009  int n;
16010  for(n = targetdata->nvars - 1; n >= 0; --n )
16011  assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
16012  }
16013 #endif
16014 
16015  /* create target constraint */
16016  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
16017  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
16018  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
16019  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
16020  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
16021 
16022  return SCIP_OKAY;
16023 }
16024 
16025 
16026 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
16027 static
16028 SCIP_DECL_CONSINITLP(consInitlpLinear)
16029 { /*lint --e{715}*/
16030  int c;
16031 
16032  assert(scip != NULL);
16033  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16034 
16035  *infeasible = FALSE;
16036 
16037  for( c = 0; c < nconss && !(*infeasible); ++c )
16038  {
16039  assert(SCIPconsIsInitial(conss[c]));
16040  SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
16041  }
16042 
16043  return SCIP_OKAY;
16044 }
16045 
16046 
16047 /** separation method of constraint handler for LP solutions */
16048 static
16049 SCIP_DECL_CONSSEPALP(consSepalpLinear)
16050 { /*lint --e{715}*/
16051  SCIP_CONSHDLRDATA* conshdlrdata;
16052  SCIP_Real loclowerbound;
16053  SCIP_Real glblowerbound;
16054  SCIP_Real cutoffbound;
16055  SCIP_Real maxbound;
16056  SCIP_Bool separatecards;
16057  SCIP_Bool cutoff;
16058  int c;
16059  int depth;
16060  int nrounds;
16061  int maxsepacuts;
16062  int ncuts;
16063 
16064  assert(scip != NULL);
16065  assert(conshdlr != NULL);
16066  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16067  assert(result != NULL);
16069  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16070  assert(conshdlrdata != NULL);
16071  depth = SCIPgetDepth(scip);
16072  nrounds = SCIPgetNSepaRounds(scip);
16073 
16074  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16075 
16076  *result = SCIP_DIDNOTRUN;
16077 
16078  /* only call the separator a given number of times at each node */
16079  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16080  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16081  return SCIP_OKAY;
16082 
16083  /* get the maximal number of cuts allowed in a separation round */
16084  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16085 
16086  /* check if we want to produce knapsack cardinality cuts at this node */
16087  loclowerbound = SCIPgetLocalLowerbound(scip);
16088  glblowerbound = SCIPgetLowerbound(scip);
16089  cutoffbound = SCIPgetCutoffbound(scip);
16090  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16091  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
16092  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
16093 
16094  *result = SCIP_DIDNOTFIND;
16095  ncuts = 0;
16096  cutoff = FALSE;
16097 
16098  /* check all useful linear constraints for feasibility */
16099  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16100  {
16101  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16102  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16103  }
16104 
16105  /* adjust return value */
16106  if( cutoff )
16107  *result = SCIP_CUTOFF;
16108  else if( ncuts > 0 )
16109  *result = SCIP_SEPARATED;
16110 
16111  /* combine linear constraints to get more cuts */
16112  /**@todo further cuts of linear constraints */
16113 
16114  return SCIP_OKAY;
16115 }
16116 
16117 
16118 /** separation method of constraint handler for arbitrary primal solutions */
16119 static
16120 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16121 { /*lint --e{715}*/
16122  SCIP_CONSHDLRDATA* conshdlrdata;
16123  int c;
16124  int depth;
16125  int nrounds;
16126  int maxsepacuts;
16127  int ncuts;
16128  SCIP_Bool cutoff;
16129 
16130  assert(scip != NULL);
16131  assert(conshdlr != NULL);
16132  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16133  assert(result != NULL);
16134 
16135  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16136  assert(conshdlrdata != NULL);
16137  depth = SCIPgetDepth(scip);
16138  nrounds = SCIPgetNSepaRounds(scip);
16140  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16141 
16142  *result = SCIP_DIDNOTRUN;
16143 
16144  /* only call the separator a given number of times at each node */
16145  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16146  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16147  return SCIP_OKAY;
16148 
16149  /* get the maximal number of cuts allowed in a separation round */
16150  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16151 
16152  *result = SCIP_DIDNOTFIND;
16153  ncuts = 0;
16154  cutoff = FALSE;
16155 
16156  /* check all useful linear constraints for feasibility */
16157  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16158  {
16159  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16160  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16161  }
16162 
16163  /* adjust return value */
16164  if( cutoff )
16165  *result = SCIP_CUTOFF;
16166  else if( ncuts > 0 )
16167  *result = SCIP_SEPARATED;
16168 
16169  /* combine linear constraints to get more cuts */
16170  /**@todo further cuts of linear constraints */
16171 
16172  return SCIP_OKAY;
16173 }
16174 
16175 
16176 /** constraint enforcing method of constraint handler for LP solutions */
16177 static
16178 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16179 { /*lint --e{715}*/
16180  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16181 
16182  return SCIP_OKAY;
16183 }
16184 
16185 /** constraint enforcing method of constraint handler for relaxation solutions */
16186 static
16187 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16188 { /*lint --e{715}*/
16189  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16190 
16191  return SCIP_OKAY;
16192 }
16193 
16194 /** constraint enforcing method of constraint handler for pseudo solutions */
16195 static
16196 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16197 { /*lint --e{715}*/
16198  SCIP_CONSHDLRDATA* conshdlrdata;
16199  SCIP_Bool checkrelmaxabs;
16200  SCIP_Bool violated;
16201  int c;
16202 
16203  assert(scip != NULL);
16204  assert(conshdlr != NULL);
16205  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16206  assert(result != NULL);
16207 
16208  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16209  assert(conshdlrdata != NULL);
16210 
16211  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16212 
16213  SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16214 
16215  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16216  if( objinfeasible )
16217  {
16218  SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16219 
16220  *result = SCIP_DIDNOTRUN;
16221  return SCIP_OKAY;
16222  }
16223 
16224  /* check all linear constraints for feasibility */
16225  violated = FALSE;
16226  for( c = 0; c < nconss && !violated; ++c )
16227  {
16228  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16229  }
16230 
16231  if( violated )
16232  *result = SCIP_INFEASIBLE;
16233  else
16234  *result = SCIP_FEASIBLE;
16235 
16236  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16237 
16238  return SCIP_OKAY;
16239 }
16240 
16241 
16242 /** feasibility check method of constraint handler for integral solutions */
16243 static
16244 SCIP_DECL_CONSCHECK(consCheckLinear)
16245 { /*lint --e{715}*/
16246  SCIP_CONSHDLRDATA* conshdlrdata;
16247  SCIP_Bool checkrelmaxabs;
16248  int c;
16249 
16250  assert(scip != NULL);
16251  assert(conshdlr != NULL);
16252  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16253  assert(result != NULL);
16254 
16255  *result = SCIP_FEASIBLE;
16256 
16257  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16258  assert(conshdlrdata != NULL);
16259 
16260  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16261 
16262  /*debugMsg(scip, "Check method of linear constraints\n");*/
16264  /* check all linear constraints for feasibility */
16265  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16266  {
16267  SCIP_Bool violated = FALSE;
16268  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16269 
16270  if( violated )
16271  {
16272  *result = SCIP_INFEASIBLE;
16273 
16274  if( printreason )
16275  {
16276  SCIP_CONSDATA* consdata;
16277  SCIP_Real activity;
16278 
16279  consdata = SCIPconsGetData(conss[c]);
16280  assert( consdata != NULL);
16281 
16282  activity = consdataGetActivity(scip, consdata, sol);
16283 
16284  SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16285  SCIPinfoMessage(scip, NULL, ";\n");
16286 
16287  if( activity == SCIP_INVALID ) /*lint !e777*/
16288  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16289  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16290  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16291  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16292  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16293  }
16294  }
16295  }
16296 
16297  return SCIP_OKAY;
16298 }
16299 
16300 
16301 /** domain propagation method of constraint handler */
16302 static
16303 SCIP_DECL_CONSPROP(consPropLinear)
16304 { /*lint --e{715}*/
16305  SCIP_CONSHDLRDATA* conshdlrdata;
16306  SCIP_Bool rangedrowpropagation = FALSE;
16307  SCIP_Bool tightenbounds;
16308  SCIP_Bool cutoff;
16309 
16310  int nchgbds;
16311  int i;
16312 
16313  assert(scip != NULL);
16314  assert(conshdlr != NULL);
16315  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16316  assert(result != NULL);
16317 
16318  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16319  assert(conshdlrdata != NULL);
16320 
16321  /*debugMsg(scip, "Prop method of linear constraints\n");*/
16323  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16324  if( SCIPinProbing(scip) )
16325  tightenbounds = TRUE;
16326  else
16327  {
16328  int depth;
16329  int propfreq;
16330  int tightenboundsfreq;
16331  int rangedrowfreq;
16332 
16333  depth = SCIPgetDepth(scip);
16334  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16335  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16336  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16337  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16338 
16339  /* check if we want to do ranged row propagation */
16340  rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16341  rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16342  rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16343  rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16344  rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16345  && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16346  }
16347 
16348  cutoff = FALSE;
16349  nchgbds = 0;
16350 
16351  /* process constraints marked for propagation */
16352  for( i = 0; i < nmarkedconss && !cutoff; i++ )
16353  {
16354  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
16355  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16356  conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16357  }
16358 
16359  /* adjust result code */
16360  if( cutoff )
16361  *result = SCIP_CUTOFF;
16362  else if( nchgbds > 0 )
16363  *result = SCIP_REDUCEDDOM;
16364  else
16365  *result = SCIP_DIDNOTFIND;
16366 
16367  return SCIP_OKAY;
16368 }
16369 
16370 
16371 #define MAXCONSPRESOLROUNDS 10
16372 /** presolving method of constraint handler */
16373 static
16374 SCIP_DECL_CONSPRESOL(consPresolLinear)
16375 { /*lint --e{715}*/
16376  SCIP_CONSHDLRDATA* conshdlrdata;
16377  SCIP_CONS* cons;
16378  SCIP_CONSDATA* consdata;
16379  SCIP_Real minactivity;
16380  SCIP_Real maxactivity;
16381  SCIP_Bool minactisrelax;
16382  SCIP_Bool maxactisrelax;
16383  SCIP_Bool isminsettoinfinity;
16384  SCIP_Bool ismaxsettoinfinity;
16385  SCIP_Bool cutoff;
16386  int oldnfixedvars;
16387  int oldnaggrvars;
16388  int oldnchgbds;
16389  int oldndelconss;
16390  int oldnupgdconss;
16391  int oldnchgcoefs;
16392  int oldnchgsides;
16393  int firstchange;
16394  int firstupgradetry;
16395  int c;
16396 
16397  assert(scip != NULL);
16398  assert(conshdlr != NULL);
16399  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16400  assert(result != NULL);
16401 
16402  /*debugMsg(scip, "Presol method of linear constraints\n");*/
16403 
16404  /* remember old preprocessing counters */
16405  cutoff = FALSE;
16406  oldnfixedvars = *nfixedvars;
16407  oldnaggrvars = *naggrvars;
16408  oldnchgbds = *nchgbds;
16409  oldndelconss = *ndelconss;
16410  oldnupgdconss = *nupgdconss;
16411  oldnchgcoefs = *nchgcoefs;
16412  oldnchgsides = *nchgsides;
16413 
16414  /* get constraint handler data */
16415  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16416  assert(conshdlrdata != NULL);
16417 
16418  /* process single constraints */
16419  firstchange = INT_MAX;
16420  firstupgradetry = INT_MAX;
16421  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16422  {
16423  int npresolrounds;
16424  SCIP_Bool infeasible;
16425 
16426  infeasible = FALSE;
16427 
16428  cons = conss[c];
16429  assert(SCIPconsIsActive(cons));
16430  consdata = SCIPconsGetData(cons);
16431  assert(consdata != NULL);
16432 
16433  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16434  if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16435  {
16436  consdata->lhs = consdata->rhs;
16437  assert(consdata->row == NULL);
16438  }
16439 
16440  if( consdata->eventdata == NULL )
16441  {
16442  /* catch bound change events of variables */
16443  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16444  assert(consdata->eventdata != NULL);
16445  }
16446 
16447  /* constraint should not be already presolved in the initial round */
16448  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16449  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16450  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16451  assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16452 
16453  /* incorporate fixings and aggregations in constraint */
16454  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16455 
16456  if( infeasible )
16457  {
16458  SCIPdebugMsg(scip, " -> infeasible fixing\n");
16459  cutoff = TRUE;
16460  break;
16461  }
16462 
16463  assert(consdata->removedfixings);
16464 
16465  /* we can only presolve linear constraints, that are not modifiable */
16466  if( SCIPconsIsModifiable(cons) )
16467  continue;
16468 
16469  /* remember the first changed constraint to begin the next aggregation round with */
16470  if( firstchange == INT_MAX && consdata->changed )
16471  firstchange = c;
16472 
16473  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16474  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16475  firstupgradetry = c;
16476 
16477  /* check, if constraint is already preprocessed */
16478  if( consdata->presolved )
16479  continue;
16480 
16481  assert(SCIPconsIsActive(cons));
16482 
16483  SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16484  SCIPdebugPrintCons(scip, cons, NULL);
16485 
16486  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16487  * to avoid nearly infinite cycling due to very small bound changes)
16488  */
16489  npresolrounds = 0;
16490  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16491  {
16492  assert(!cutoff);
16493  npresolrounds++;
16494 
16495  /* mark constraint being presolved and propagated */
16496  consdata->presolved = TRUE;
16497  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
16498 
16499  /* normalize constraint */
16500  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16501 
16502  if( infeasible )
16503  {
16504  SCIPdebugMsg(scip, " -> infeasible normalization\n");
16505  cutoff = TRUE;
16506  break;
16507  }
16508 
16509  /* tighten left and right hand side due to integrality */
16510  SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16511 
16512  if( infeasible )
16513  {
16514  SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16515  cutoff = TRUE;
16516  break;
16517  }
16518 
16519  /* check bounds */
16520  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16521  {
16522  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16523  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16524  cutoff = TRUE;
16525  break;
16526  }
16527 
16528  /* tighten variable's bounds */
16529  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16530  if( cutoff )
16531  break;
16532 
16533  /* check for fixed variables */
16534  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16535  if( cutoff )
16536  break;
16537 
16538  /* check constraint for infeasibility and redundancy */
16539  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
16540  &isminsettoinfinity, &ismaxsettoinfinity);
16541  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16542  {
16543  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16544  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16545  cutoff = TRUE;
16546  break;
16547  }
16548  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16549  {
16550  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16551  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16552  SCIP_CALL( SCIPdelCons(scip, cons) );
16553  assert(!SCIPconsIsActive(cons));
16554 
16555  if( !consdata->upgraded )
16556  (*ndelconss)++;
16557  break;
16558  }
16559  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16560  {
16561  SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16562  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16563  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16564  if( !consdata->upgraded )
16565  (*nchgsides)++;
16566  }
16567  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16568  {
16569  SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16570  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16571  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
16572  if( !consdata->upgraded )
16573  (*nchgsides)++;
16574  }
16575 
16576  /* handle empty constraint */
16577  if( consdata->nvars == 0 )
16578  {
16579  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16580  {
16581  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16582  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16583  cutoff = TRUE;
16584  }
16585  else
16586  {
16587  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16588  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16589  SCIP_CALL( SCIPdelCons(scip, cons) );
16590  assert(!SCIPconsIsActive(cons));
16591 
16592  if( !consdata->upgraded )
16593  (*ndelconss)++;
16594  }
16595  break;
16596  }
16597 
16598  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16599  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16600 
16601  /* try to simplify inequalities */
16602  if( conshdlrdata->simplifyinequalities )
16603  {
16604  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16605 
16606  if( cutoff )
16607  break;
16608  }
16609 
16610  /* aggregation variable in equations */
16611  if( conshdlrdata->aggregatevariables )
16612  {
16613  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16614  if( cutoff )
16615  break;
16616  }
16617  }
16618 
16619  if( !cutoff && !SCIPisStopped(scip) )
16620  {
16621  /* perform ranged row propagation */
16622  if( conshdlrdata->rangedrowpropagation )
16623  {
16624  int lastnfixedvars;
16625 
16626  lastnfixedvars = *nfixedvars;
16627 
16628  SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16629  if( !cutoff )
16630  {
16631  if( lastnfixedvars < *nfixedvars )
16632  {
16633  SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16634  }
16635  }
16636  }
16637 
16638  /* extract cliques from constraint */
16639  if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16640  {
16641  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16642  nfixedvars, nchgbds, &cutoff) );
16643 
16644  /* check if the constraint got redundant or infeasible */
16645  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16646  {
16647  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16648  {
16649  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16650  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16651  cutoff = TRUE;
16652  }
16653  else
16654  {
16655  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16656  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16657  SCIP_CALL( SCIPdelCons(scip, cons) );
16658  assert(!SCIPconsIsActive(cons));
16659 
16660  if( !consdata->upgraded )
16661  (*ndelconss)++;
16662  }
16663  }
16664  }
16665 
16666  /* convert special equalities */
16667  if( !cutoff && SCIPconsIsActive(cons) )
16668  {
16669  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16670  }
16671 
16672  /* apply dual presolving for variables that appear in only one constraint */
16673  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16674  {
16675  SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16676  }
16677 
16678  /* check if an inequality is parallel to the objective function */
16679  if( !cutoff && SCIPconsIsActive(cons) )
16680  {
16681  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16682  }
16683 
16684  /* remember the first changed constraint to begin the next aggregation round with */
16685  if( firstchange == INT_MAX && consdata->changed )
16686  firstchange = c;
16687 
16688  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16689  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16690  firstupgradetry = c;
16691  }
16692 
16693  /* singleton column stuffing */
16694  if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16695  (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16696  {
16697  SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16698  conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16699 
16700  /* handle empty constraint */
16701  if( consdata->nvars == 0 )
16702  {
16703  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16704  {
16705  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16706  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16707  cutoff = TRUE;
16708  }
16709  else
16710  {
16711  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16712  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16713  SCIP_CALL( SCIPdelCons(scip, cons) );
16714  assert(!SCIPconsIsActive(cons));
16715 
16716  if( !consdata->upgraded )
16717  (*ndelconss)++;
16718  }
16719  break;
16720  }
16721  }
16722  }
16723 
16724  /* process pairs of constraints: check them for redundancy and try to aggregate them;
16725  * only apply this expensive procedure in exhaustive presolving timing
16726  */
16727  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16728  {
16729  assert(firstchange >= 0);
16730 
16731  if( firstchange < nconss && conshdlrdata->presolusehashing )
16732  {
16733  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16734  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16735  ndelconss, nchgsides) );
16736  }
16737 
16738  if( firstchange < nconss && conshdlrdata->presolpairwise )
16739  {
16740  SCIP_CONS** usefulconss;
16741  int nusefulconss;
16742  int firstchangenew;
16743  SCIP_Longint npaircomparisons;
16744 
16745  npaircomparisons = 0;
16746  oldndelconss = *ndelconss;
16747  oldnchgsides = *nchgsides;
16748  oldnchgcoefs = *nchgcoefs;
16749 
16750  /* allocate temporary memory */
16751  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16752 
16753  nusefulconss = 0;
16754  firstchangenew = -1;
16755  for( c = 0; c < nconss; ++c )
16756  {
16757  /* update firstchange */
16758  if( c == firstchange )
16759  firstchangenew = nusefulconss;
16760 
16761  /* ignore inactive and modifiable constraints */
16762  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16763  continue;
16764 
16765  usefulconss[nusefulconss] = conss[c];
16766  ++nusefulconss;
16767  }
16768  firstchange = firstchangenew;
16769  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16770 
16771  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16772  {
16773  /* constraint has become inactive or modifiable during pairwise presolving */
16774  if( usefulconss[c] == NULL )
16775  continue;
16776 
16777  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16778 
16779  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16780  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16781  &cutoff, ndelconss, nchgsides, nchgcoefs) );
16782 
16783  if( npaircomparisons > conshdlrdata->nmincomparisons )
16784  {
16785  assert(npaircomparisons > 0);
16786  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16787  break;
16788  oldndelconss = *ndelconss;
16789  oldnchgsides = *nchgsides;
16790  oldnchgcoefs = *nchgcoefs;
16791  npaircomparisons = 0;
16792  }
16793  }
16794  /* free temporary memory */
16795  SCIPfreeBufferArray(scip, &usefulconss);
16796  }
16797  }
16798 
16799  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16800  * in linear constraints and we therefore have full information about it
16801  */
16802  if( !cutoff && firstupgradetry < nconss
16803  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16804  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16805  )
16806  {
16807  if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16808  {
16809  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16810  }
16811  }
16812 
16813  /* try to upgrade constraints into a more specific constraint type;
16814  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16815  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16816  */
16817  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16818  {
16819  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16820  {
16821  cons = conss[c];
16822 
16823  /* don't upgrade modifiable constraints */
16824  if( SCIPconsIsModifiable(cons) )
16825  continue;
16826 
16827  consdata = SCIPconsGetData(cons);
16828  assert(consdata != NULL);
16829 
16830  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16831  if( consdata->upgradetried )
16832  continue;
16833  /* @todo force that upgrade will be performed later? */
16834  if( !consdata->presolved )
16835  continue;
16836 
16837  consdata->upgradetried = TRUE;
16838  if( SCIPconsIsActive(cons) )
16839  {
16840  SCIP_CONS* upgdcons;
16841 
16842  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16843  if( upgdcons != NULL )
16844  {
16845  /* add the upgraded constraint to the problem */
16846  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16847  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16848  (*nupgdconss)++;
16849 
16850  /* mark the linear constraint being upgraded and to be removed after presolving;
16851  * don't delete it directly, because it may help to preprocess other linear constraints
16852  */
16853  assert(!consdata->upgraded);
16854  consdata->upgraded = TRUE;
16855 
16856  /* delete upgraded inequalities immediately;
16857  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16858  */
16859  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16860  || !conshdlrdata->presolpairwise
16861  || (conshdlrdata->maxaggrnormscale == 0.0) )
16862  {
16863  SCIP_CALL( SCIPdelCons(scip, cons) );
16864  }
16865  }
16866  }
16867  }
16868  }
16869 
16870  /* return the correct result code */
16871  if( cutoff )
16872  *result = SCIP_CUTOFF;
16873  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16874  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16875  *result = SCIP_SUCCESS;
16876  else
16877  *result = SCIP_DIDNOTFIND;
16878 
16879  return SCIP_OKAY;
16880 }
16881 
16882 
16883 /** propagation conflict resolving method of constraint handler */
16884 static
16885 SCIP_DECL_CONSRESPROP(consRespropLinear)
16886 { /*lint --e{715}*/
16887  assert(scip != NULL);
16888  assert(cons != NULL);
16889  assert(result != NULL);
16890 
16891  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16892 
16893  return SCIP_OKAY;
16894 }
16895 
16896 
16897 /** variable rounding lock method of constraint handler */
16898 static
16899 SCIP_DECL_CONSLOCK(consLockLinear)
16900 { /*lint --e{715}*/
16901  SCIP_CONSDATA* consdata;
16902  SCIP_Bool haslhs;
16903  SCIP_Bool hasrhs;
16904  int i;
16905 
16906  assert(scip != NULL);
16907  assert(cons != NULL);
16908  consdata = SCIPconsGetData(cons);
16909  assert(consdata != NULL);
16910 
16911  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16912  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16913 
16914  /* update rounding locks of every single variable */
16915  for( i = 0; i < consdata->nvars; ++i )
16916  {
16917  if( SCIPisPositive(scip, consdata->vals[i]) )
16918  {
16919  if( haslhs )
16920  {
16921  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16922  }
16923  if( hasrhs )
16924  {
16925  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16926  }
16927  }
16928  else
16929  {
16930  if( haslhs )
16931  {
16932  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16933  }
16934  if( hasrhs )
16935  {
16936  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16937  }
16938  }
16939  }
16940 
16941  return SCIP_OKAY;
16942 }
16943 
16944 
16945 /** variable deletion method of constraint handler */
16946 static
16947 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16948 {
16949  assert(scip != NULL);
16950  assert(conshdlr != NULL);
16951  assert(conss != NULL || nconss == 0);
16952 
16953  if( nconss > 0 )
16954  {
16955  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16956  }
16957 
16958  return SCIP_OKAY;
16959 }
16960 
16961 /** constraint display method of constraint handler */
16962 static
16963 SCIP_DECL_CONSPRINT(consPrintLinear)
16964 { /*lint --e{715}*/
16965  assert(scip != NULL);
16966  assert(conshdlr != NULL);
16967  assert(cons != NULL);
16968 
16969  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16970 
16971  return SCIP_OKAY;
16972 }
16973 
16974 /** constraint copying method of constraint handler */
16975 static
16976 SCIP_DECL_CONSCOPY(consCopyLinear)
16977 { /*lint --e{715}*/
16978  SCIP_VAR** sourcevars;
16979  SCIP_Real* sourcecoefs;
16980  const char* consname;
16981  int nvars;
16983  assert(scip != NULL);
16984  assert(sourcescip != NULL);
16985  assert(sourcecons != NULL);
16986 
16987  /* get variables and coefficients of the source constraint */
16988  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16989  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16990  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16991 
16992  if( name != NULL )
16993  consname = name;
16994  else
16995  consname = SCIPconsGetName(sourcecons);
16996 
16997  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16998  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16999  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
17000  assert(cons != NULL || *valid == FALSE);
17001 
17002  /* @todo should also the checkabsolute flag of the constraint be copied? */
17003 
17004  return SCIP_OKAY;
17005 }
17006 
17007 /** find operators '<=', '==', '>=', [free] in input string and return those places
17008  *
17009  * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
17010  */
17011 static
17012 void findOperators(
17013  const char* str, /**< null terminated input string */
17014  char** firstoperator, /**< pointer to store the string starting at the first operator */
17015  char** secondoperator, /**< pointer to store the string starting at the second operator */
17016  SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
17017  )
17018 {
17019  char* curr;
17020 
17021  assert(str != NULL);
17022  assert(firstoperator != NULL);
17023  assert(secondoperator != NULL);
17024 
17025  *firstoperator = NULL;
17026  *secondoperator = NULL;
17027 
17028  curr = (char*)str;
17029  *success = TRUE;
17030 
17031  /* loop over the input string to find all operators */
17032  while( *curr && *success )
17033  {
17034  SCIP_Bool found = FALSE;
17035  int increment = 1;
17036 
17037  /* try if we found a possible operator */
17038  switch( *curr )
17039  {
17040  case '<':
17041  case '=':
17042  case '>':
17043 
17044  /* check if the two characters curr[0,1] form an operator together */
17045  if( curr[1] == '=' )
17046  {
17047  found = TRUE;
17048 
17049  /* update increment to continue after this operator */
17050  increment = 2;
17051  }
17052  break;
17053  case '[':
17054  if( strncmp(curr, "[free]", 6) == 0 )
17055  {
17056  found = TRUE;
17057 
17058  /* update increment to continue after this operator */
17059  increment = 6;
17060  }
17061  break;
17062  default:
17063  break;
17064  }
17065 
17066  /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
17067  if( found )
17068  {
17069  if( *firstoperator == NULL )
17070  {
17071  *firstoperator = curr;
17072  }
17073  else
17074  {
17075  if( *secondoperator != NULL )
17076  {
17077  SCIPerrorMessage("Found more than two operators in line %s\n", str);
17078  *success = FALSE;
17079  }
17080  else if( strncmp(*firstoperator, "<=", 2) != 0 )
17081  {
17082  SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17083  *success = FALSE;
17084  }
17085  else if( strncmp(curr, "<=", 2) != 0 )
17086  {
17087  SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17088  *success = FALSE;
17089  }
17090 
17091  *secondoperator = curr;
17092  }
17093  }
17094 
17095  curr += increment;
17096  }
17097 
17098  /* check if we did find at least one operator */
17099  if( *success )
17100  {
17101  if( *firstoperator == NULL )
17102  {
17103  SCIPerrorMessage("Could not find any operator in line %s\n", str);
17104  *success = FALSE;
17105  }
17106  }
17107 }
17108 
17109 /** constraint parsing method of constraint handler */
17110 static
17111 SCIP_DECL_CONSPARSE(consParseLinear)
17112 { /*lint --e{715}*/
17113  SCIP_VAR** vars;
17114  SCIP_Real* coefs;
17115  int nvars;
17116  int coefssize;
17117  int requsize;
17118  SCIP_Real lhs;
17119  SCIP_Real rhs;
17120  char* endptr;
17121  char* firstop;
17122  char* secondop;
17123  SCIP_Bool operatorsuccess;
17124  char* lhsstrptr;
17125  char* rhsstrptr;
17126  char* varstrptr;
17127 
17128  assert(scip != NULL);
17129  assert(success != NULL);
17130  assert(str != NULL);
17131  assert(name != NULL);
17132  assert(cons != NULL);
17133 
17134  /* set left and right hand side to their default values */
17135  lhs = -SCIPinfinity(scip);
17136  rhs = SCIPinfinity(scip);
17137 
17138  (*success) = FALSE;
17139 
17140  /* return of string empty */
17141  if( !*str )
17142  return SCIP_OKAY;
17143 
17144  /* ignore whitespace */
17145  SCIP_CALL( SCIPskipSpace((char**)&str) );
17146 
17147  /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17148  * and the special word [free]
17149  */
17150  findOperators(str, &firstop, &secondop, &operatorsuccess);
17151 
17152  /* if the grammar is not valid for parsing a linear constraint, return */
17153  if( ! operatorsuccess )
17154  return SCIP_OKAY;
17155 
17156  varstrptr = (char *)str;
17157  lhsstrptr = rhsstrptr = NULL;
17158  assert(firstop != NULL);
17159 
17160  /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17161  switch( *firstop )
17162  {
17163  case '<':
17164  assert(firstop[1] == '=');
17165  /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17166  if( secondop != NULL )
17167  {
17168  assert(secondop[0] == '<' && secondop[1] == '=');
17169  lhsstrptr = (char *)str;
17170  varstrptr = firstop + 2;
17171  rhsstrptr = secondop + 2;
17172  }
17173  else
17174  {
17175  /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17176  lhsstrptr = NULL;
17177  varstrptr = (char *)str;
17178  rhsstrptr = firstop + 2;
17179  }
17180  break;
17181  case '>':
17182  assert(firstop[1] == '=');
17183  assert(secondop == NULL);
17184  /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17185  lhsstrptr = firstop + 2;
17186  break;
17187  case '=':
17188  assert(firstop[1] == '=');
17189  assert(secondop == NULL);
17190  /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17191  rhsstrptr = firstop + 2;
17192  lhsstrptr = firstop + 2;
17193  break;
17194  case '[':
17195  assert(strncmp(firstop, "[free]", 6) == 0);
17196  assert(secondop == NULL);
17197  /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17198  break;
17199  default:
17200  /* it should not be possible that a different character appears in that position */
17201  SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17202  return SCIP_READERROR;
17203  }
17204 
17205  /* parse left hand side, if necessary */
17206  if( lhsstrptr != NULL )
17207  {
17208  if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17209  {
17210  SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17211  return SCIP_OKAY;
17212  }
17213 
17214  /* in case of an equation, assign the left also to the right hand side */
17215  if( rhsstrptr == lhsstrptr )
17216  rhs = lhs;
17217  }
17218 
17219  /* parse right hand side, if different from left hand side */
17220  if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17221  {
17222  if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17223  {
17224  SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17225  return SCIP_OKAY;
17226  }
17227  }
17228 
17229  /* initialize buffers for storing the variables and coefficients */
17230  coefssize = 100;
17231  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17232  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17233 
17234  assert(varstrptr != NULL);
17235 
17236  /* parse linear sum to get variables and coefficients */
17237  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17238 
17239  if( *success && requsize > coefssize )
17240  {
17241  /* realloc buffers and try again */
17242  coefssize = requsize;
17243  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17244  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17245 
17246  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17247  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17248  }
17249 
17250  if( !*success )
17251  {
17252  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17253  }
17254  else
17255  {
17256  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17257  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17258  }
17259 
17260  SCIPfreeBufferArray(scip, &coefs);
17261  SCIPfreeBufferArray(scip, &vars);
17262 
17263  return SCIP_OKAY;
17264 }
17265 
17266 
17267 /** constraint method of constraint handler which returns the variables (if possible) */
17268 static
17269 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17270 { /*lint --e{715}*/
17271  SCIP_CONSDATA* consdata;
17272 
17273  consdata = SCIPconsGetData(cons);
17274  assert(consdata != NULL);
17275 
17276  if( varssize < consdata->nvars )
17277  (*success) = FALSE;
17278  else
17279  {
17280  assert(vars != NULL);
17281 
17282  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17283  (*success) = TRUE;
17284  }
17285 
17286  return SCIP_OKAY;
17287 }
17289 /**! [Callback for the number of variables]*/
17290 /** constraint method of constraint handler which returns the number of variables (if possible) */
17291 static
17292 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17293 { /*lint --e{715}*/
17294  SCIP_CONSDATA* consdata;
17295 
17296  consdata = SCIPconsGetData(cons);
17297  assert(consdata != NULL);
17298 
17299  (*nvars) = consdata->nvars;
17300  (*success) = TRUE;
17301 
17302  return SCIP_OKAY;
17303 }
17304 /**! [Callback for the number of variables]*/
17305 
17306 /** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17307 static
17308 SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17309 { /*lint --e{715}*/
17310  SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17312  return SCIP_OKAY;
17313 }
17314 
17315 /** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17316 static
17317 SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17318 { /*lint --e{715}*/
17319  SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17320 
17321  return SCIP_OKAY;
17322 }
17323 
17324 /*
17325  * Callback methods of event handler
17326  */
17328 /** execution method of event handler */
17329 static
17330 SCIP_DECL_EVENTEXEC(eventExecLinear)
17331 { /*lint --e{715}*/
17332  SCIP_CONS* cons;
17333  SCIP_CONSDATA* consdata;
17334  SCIP_VAR* var;
17335  SCIP_EVENTTYPE eventtype;
17337  assert(scip != NULL);
17338  assert(eventhdlr != NULL);
17339  assert(eventdata != NULL);
17340  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17341  assert(event != NULL);
17342 
17343  cons = eventdata->cons;
17344  assert(cons != NULL);
17345  consdata = SCIPconsGetData(cons);
17346  assert(consdata != NULL);
17347 
17348  /* we can skip events droped for deleted constraints */
17349  if( SCIPconsIsDeleted(cons) )
17350  return SCIP_OKAY;
17351 
17352  eventtype = SCIPeventGetType(event);
17353  var = SCIPeventGetVar(event);
17354 
17355  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17356  {
17357  SCIP_Real oldbound;
17358  SCIP_Real newbound;
17359  SCIP_Real val;
17360  int varpos;
17361 
17362  varpos = eventdata->varpos;
17363  assert(0 <= varpos && varpos < consdata->nvars);
17364  oldbound = SCIPeventGetOldbound(event);
17365  newbound = SCIPeventGetNewbound(event);
17366  assert(var != NULL);
17367  assert(consdata->vars[varpos] == var);
17368  val = consdata->vals[varpos];
17369 
17370  /* we only need to update the activities if the constraint is active,
17371  * otherwise we mark them to be invalid
17372  */
17373  if( SCIPconsIsActive(cons) )
17374  {
17375  /* update the activity values */
17376  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17377  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17378  else
17379  {
17380  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17381  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17382  }
17383  }
17384  else
17385  consdataInvalidateActivities(consdata);
17386 
17387  consdata->presolved = FALSE;
17388  consdata->rangedrowpropagated = 0;
17389 
17390  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17391  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17392  {
17393  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
17394 
17395  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17396  if( consdata->maxactdeltavar == var )
17397  {
17398  consdata->maxactdelta = SCIP_INVALID;
17399  consdata->maxactdeltavar = NULL;
17400  }
17401 
17402  /* check whether bound tightening might now be successful */
17403  if( consdata->boundstightened > 0)
17404  {
17405  switch( eventtype )
17406  {
17408  if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17409  consdata->boundstightened = 0;
17410  break;
17412  if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17413  consdata->boundstightened = 0;
17414  break;
17415  default:
17416  SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17417  return SCIP_INVALIDDATA;
17418  }
17419  }
17420  }
17421  /* update maximal activity delta if a bound was relaxed */
17422  else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17423  {
17424  SCIP_Real lb;
17425  SCIP_Real ub;
17426  SCIP_Real domain;
17427  SCIP_Real delta;
17428 
17429  assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17430 
17431  lb = SCIPvarGetLbLocal(var);
17432  ub = SCIPvarGetUbLocal(var);
17433 
17434  domain = ub - lb;
17435  delta = REALABS(val) * domain;
17436 
17437  if( delta > consdata->maxactdelta )
17438  {
17439  consdata->maxactdelta = delta;
17440  consdata->maxactdeltavar = var;
17441  }
17442  }
17443  }
17444  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17445  {
17446  /* we want to remove the fixed variable */
17447  consdata->presolved = FALSE;
17448  consdata->removedfixings = FALSE;
17449  consdata->rangedrowpropagated = 0;
17450 
17451  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17452  if( consdata->maxactdeltavar == var )
17453  {
17454  consdata->maxactdelta = SCIP_INVALID;
17455  consdata->maxactdeltavar = NULL;
17456  }
17457  }
17458  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17459  {
17460  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17461  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17462  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17463  consdata->presolved = FALSE;
17464  }
17465  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17466  {
17467  SCIP_Real oldbound;
17468  SCIP_Real newbound;
17469  SCIP_Real val;
17470  int varpos;
17471 
17472  varpos = eventdata->varpos;
17473  assert(0 <= varpos && varpos < consdata->nvars);
17474  oldbound = SCIPeventGetOldbound(event);
17475  newbound = SCIPeventGetNewbound(event);
17476  assert(var != NULL);
17477  assert(consdata->vars[varpos] == var);
17478  val = consdata->vals[varpos];
17479 
17480  consdata->rangedrowpropagated = 0;
17481 
17482  /* update the activity values */
17483  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17484  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17485  else
17486  {
17487  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17488  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17489  }
17490 
17491  /* if the variable is binary but not fixed it had to become binary due to this global change */
17492  if( SCIPvarIsBinary(var) && SCIPisGT(scip, SCIPvarGetUbGlobal(var), SCIPvarGetLbGlobal(var)) )
17493  {
17494  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
17495  consdata->indexsorted = FALSE;
17496  else
17497  consdata->coefsorted = FALSE;
17498  }
17499  }
17500  else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17501  {
17502  assert(SCIPgetStage(scip) < SCIP_STAGE_PRESOLVED);
17503 
17504  /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17505  consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17506 
17507  /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17508  consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17509  }
17510  else
17511  {
17512  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17513  consdata->varsdeleted = TRUE;
17514  }
17515 
17516  return SCIP_OKAY;
17517 }
17518 
17519 
17520 /*
17521  * Callback methods of conflict handler
17522  */
17523 
17524 /** conflict processing method of conflict handler (called when conflict was found) */
17525 static
17526 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17527 { /*lint --e{715}*/
17528  SCIP_VAR** vars;
17529  SCIP_Real* vals;
17530  SCIP_Real lhs;
17531  int i;
17532 
17533  assert(scip != NULL);
17534  assert(conflicthdlr != NULL);
17535  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17536  assert(bdchginfos != NULL || nbdchginfos == 0);
17537  assert(result != NULL);
17538 
17539  /* don't process already resolved conflicts */
17540  if( resolved )
17541  {
17542  *result = SCIP_DIDNOTRUN;
17543  return SCIP_OKAY;
17544  }
17546  *result = SCIP_DIDNOTFIND;
17547 
17548  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17549  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17550  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17551  lhs = 1.0;
17552  for( i = 0; i < nbdchginfos; ++i )
17553  {
17554  assert(bdchginfos != NULL);
17555 
17556  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17557 
17558  /* we can only treat binary variables */
17559  /**@todo extend linear conflict constraints to some non-binary cases */
17560  if( !SCIPvarIsBinary(vars[i]) )
17561  break;
17562 
17563  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17564  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17565  vals[i] = 1.0;
17566  else
17567  {
17568  vals[i] = -1.0;
17569  lhs -= 1.0;
17570  }
17571  }
17572 
17573  if( i == nbdchginfos )
17574  {
17575  SCIP_CONS* cons;
17576  SCIP_CONS* upgdcons;
17577  char consname[SCIP_MAXSTRLEN];
17578 
17579  /* create a constraint out of the conflict set */
17580  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
17581  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17582  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17583 
17584  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17585  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17586  if( upgdcons != NULL )
17587  {
17588  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17589  cons = upgdcons;
17590  }
17591 
17592  /* add conflict to SCIP */
17593  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17594 
17595  *result = SCIP_CONSADDED;
17596  }
17597 
17598  /* free temporary memory */
17599  SCIPfreeBufferArray(scip, &vals);
17600  SCIPfreeBufferArray(scip, &vars);
17601 
17602  return SCIP_OKAY;
17603 }
17604 
17605 
17606 /*
17607  * Nonlinear constraint upgrading
17608  */
17609 
17610 /** tries to upgrade a nonlinear constraint into a linear constraint */
17611 static
17612 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17613 {
17614  SCIP_CONSDATA* consdata;
17615  SCIP_EXPR* expr;
17616  SCIP_Real lhs;
17617  SCIP_Real rhs;
17618  int i;
17619 
17620  assert(nupgdconss != NULL);
17621  assert(upgdconss != NULL);
17622  assert(upgdconsssize > 0);
17623 
17624  expr = SCIPgetExprNonlinear(cons);
17625  assert(expr != NULL);
17626 
17627  /* not a linear constraint if the expression is not a sum
17628  * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17629  */
17630  if( !SCIPisExprSum(scip, expr) )
17631  return SCIP_OKAY;
17632 
17633  /* if at least one child is not a variable, then not a linear constraint */
17634  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17635  if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17636  return SCIP_OKAY;
17637 
17638  /* consider constant part of the sum expression */
17639  lhs = SCIPisInfinity(scip, -SCIPgetLhsNonlinear(cons)) ? -SCIPinfinity(scip) : (SCIPgetLhsNonlinear(cons) - SCIPgetConstantExprSum(expr));
17640  rhs = SCIPisInfinity(scip, SCIPgetRhsNonlinear(cons)) ? SCIPinfinity(scip) : (SCIPgetRhsNonlinear(cons) - SCIPgetConstantExprSum(expr));
17641 
17642  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17643  0, NULL, NULL, lhs, rhs,
17647  SCIPconsIsStickingAtNode(cons)) );
17648  assert(upgdconss[0] != NULL);
17649 
17650  consdata = SCIPconsGetData(upgdconss[0]);
17651 
17652  /* add linear terms */
17653  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, SCIPexprGetNChildren(expr)) );
17654  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17655  {
17656  SCIP_CALL( addCoef(scip, upgdconss[0], SCIPgetVarExprVar(SCIPexprGetChildren(expr)[i]), SCIPgetCoefsExprSum(expr)[i]) );
17657  }
17658 
17659  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17660  consdata->checkabsolute = TRUE;
17661 
17662  *nupgdconss = 1;
17663 
17664  SCIPdebugMsg(scip, "created linear constraint:\n");
17665  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17666 
17667  return SCIP_OKAY;
17668 } /*lint !e715*/
17669 
17670 /*
17671  * constraint specific interface methods
17672  */
17673 
17674 /** creates the handler for linear constraints and includes it in SCIP */
17676  SCIP* scip /**< SCIP data structure */
17677  )
17678 {
17679  SCIP_CONSHDLRDATA* conshdlrdata;
17680  SCIP_CONSHDLR* conshdlr;
17681  SCIP_EVENTHDLR* eventhdlr;
17682  SCIP_CONFLICTHDLR* conflicthdlr;
17683 
17684  assert(scip != NULL);
17685 
17686  /* create event handler for bound change events */
17688  eventExecLinear, NULL) );
17689 
17690  /* create conflict handler for linear constraints */
17692  conflictExecLinear, NULL) );
17693 
17694  /* create constraint handler data */
17695  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17696 
17697  /* include constraint handler */
17700  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17701  conshdlrdata) );
17702 
17703  assert(conshdlr != NULL);
17704 
17705  /* set non-fundamental callbacks via specific setter functions */
17706  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17707  SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17708  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17709  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17710  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17711  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17712  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17713  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17714  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17715  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17716  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17717  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17718  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17719  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17720  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17721  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
17722  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17723  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
17725  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17726  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17728  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17729  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17730  SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17731  SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17732 
17733  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17734  {
17735  /* include the linear constraint upgrade in the nonlinear constraint handler */
17737  }
17738 
17739  /* add linear constraint handler parameters */
17740  SCIP_CALL( SCIPaddIntParam(scip,
17741  "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17742  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17743  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17744  SCIP_CALL( SCIPaddIntParam(scip,
17745  "constraints/" CONSHDLR_NAME "/maxrounds",
17746  "maximal number of separation rounds per node (-1: unlimited)",
17747  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17748  SCIP_CALL( SCIPaddIntParam(scip,
17749  "constraints/" CONSHDLR_NAME "/maxroundsroot",
17750  "maximal number of separation rounds per node in the root node (-1: unlimited)",
17751  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17752  SCIP_CALL( SCIPaddIntParam(scip,
17753  "constraints/" CONSHDLR_NAME "/maxsepacuts",
17754  "maximal number of cuts separated per separation round",
17755  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17756  SCIP_CALL( SCIPaddIntParam(scip,
17757  "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17758  "maximal number of cuts separated per separation round in the root node",
17759  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17761  "constraints/" CONSHDLR_NAME "/presolpairwise",
17762  "should pairwise constraint comparison be performed in presolving?",
17763  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17765  "constraints/" CONSHDLR_NAME "/presolusehashing",
17766  "should hash table be used for detecting redundant constraints in advance",
17767  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17768  SCIP_CALL( SCIPaddIntParam(scip,
17769  "constraints/" CONSHDLR_NAME "/nmincomparisons",
17770  "number for minimal pairwise presolve comparisons",
17771  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17773  "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17774  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17775  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17777  "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17778  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17779  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17781  "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17782  "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17783  &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17785  "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17786  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17787  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17789  "constraints/" CONSHDLR_NAME "/separateall",
17790  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17791  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17793  "constraints/" CONSHDLR_NAME "/aggregatevariables",
17794  "should presolving search for aggregations in equations",
17795  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17797  "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17798  "should presolving try to simplify inequalities",
17799  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17801  "constraints/" CONSHDLR_NAME "/dualpresolving",
17802  "should dual presolving steps be performed?",
17803  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17805  "constraints/" CONSHDLR_NAME "/singletonstuffing",
17806  "should stuffing of singleton continuous variables be performed?",
17807  &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17809  "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17810  "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17811  &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17813  "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17814  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17816  "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17817  "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)?",
17818  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17820  "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17821  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17822  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17824  "constraints/" CONSHDLR_NAME "/detectlowerbound",
17825  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17826  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17828  "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17829  "should presolving try to detect subsets of constraints parallel to the objective function?",
17830  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17832  "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17833  "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17834  &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17836  "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17837  "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17838  &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17839  SCIP_CALL( SCIPaddIntParam(scip,
17840  "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17841  "maximum depth to apply ranged row propagation",
17842  &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17843  SCIP_CALL( SCIPaddIntParam(scip,
17844  "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17845  "frequency for applying ranged row propagation",
17846  &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17848  "constraints/" CONSHDLR_NAME "/multaggrremove",
17849  "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17850  &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17852  "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17853  "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17854  &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17856  "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17857  "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17858  &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17860  "constraints/" CONSHDLR_NAME "/extractcliques",
17861  "should Cliques be extracted?",
17862  &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17863 
17864  return SCIP_OKAY;
17865 }
17866 
17867 /** includes a linear constraint update method into the linear constraint handler */
17869  SCIP* scip, /**< SCIP data structure */
17870  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17871  int priority, /**< priority of upgrading method */
17872  const char* conshdlrname /**< name of the constraint handler */
17873  )
17874 {
17875  SCIP_CONSHDLR* conshdlr;
17876  SCIP_CONSHDLRDATA* conshdlrdata;
17877  SCIP_LINCONSUPGRADE* linconsupgrade;
17878  char paramname[SCIP_MAXSTRLEN];
17879  char paramdesc[SCIP_MAXSTRLEN];
17880 
17881  assert(scip != NULL);
17882  assert(linconsupgd != NULL);
17883  assert(conshdlrname != 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  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17894  assert(conshdlrdata != NULL);
17895 
17896  /* check if linear constraint update method already exists in constraint handler data */
17897  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17898  {
17899  /* create a linear constraint upgrade data object */
17900  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17901 
17902  /* insert linear constraint update method into constraint handler data */
17903  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17904 
17905  /* adds parameter to turn on and off the upgrading step */
17906  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17907  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17909  paramname, paramdesc,
17910  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17911  }
17912 
17913  return SCIP_OKAY;
17914 }
17915 
17916 /** creates and captures a linear constraint
17917  *
17918  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17919  */
17921  SCIP* scip, /**< SCIP data structure */
17922  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17923  const char* name, /**< name of constraint */
17924  int nvars, /**< number of nonzeros in the constraint */
17925  SCIP_VAR** vars, /**< array with variables of constraint entries */
17926  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17927  SCIP_Real lhs, /**< left hand side of constraint */
17928  SCIP_Real rhs, /**< right hand side of constraint */
17929  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17930  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17931  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17932  * Usually set to TRUE. */
17933  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17934  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17935  SCIP_Bool check, /**< should the constraint be checked for feasibility?
17936  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17937  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17938  * Usually set to TRUE. */
17939  SCIP_Bool local, /**< is constraint only valid locally?
17940  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17941  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17942  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17943  * adds coefficients to this constraint. */
17944  SCIP_Bool dynamic, /**< is constraint subject to aging?
17945  * Usually set to FALSE. Set to TRUE for own cuts which
17946  * are separated as constraints. */
17947  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17948  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17949  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17950  * if it may be moved to a more global node?
17951  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17952  )
17953 {
17954  SCIP_CONSHDLR* conshdlr;
17955  SCIP_CONSDATA* consdata;
17956  int j;
17957 
17958  assert(scip != NULL);
17959  assert(cons != NULL);
17960 
17961  /* find the linear constraint handler */
17962  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17963  if( conshdlr == NULL )
17964  {
17965  SCIPerrorMessage("linear constraint handler not found\n");
17966  return SCIP_PLUGINNOTFOUND;
17967  }
17968 
17969  for( j = 0; j < nvars; ++j )
17970  {
17971  if( SCIPisInfinity(scip, REALABS(vals[j])) )
17972  {
17973  SCIPerrorMessage("coefficient of variable <%s> is infinite.\n", SCIPvarGetName(vars[j]));
17974  SCIPABORT();
17975  return SCIP_INVALIDDATA;
17976  }
17977  }
17978 
17979  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17980  * constraint after presolving we have to ensure that it holds active variables
17981  */
17982  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17983  {
17984  SCIP_VAR** consvars;
17985  SCIP_Real* consvals;
17986  SCIP_Real constant = 0.0;
17987  int nconsvars;
17988  int requiredsize;
17989 
17990  nconsvars = nvars;
17991  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17992  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17993 
17994  /* get active variables for new constraint */
17995  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17996 
17997  /* if space was not enough we need to resize the buffers */
17998  if( requiredsize > nconsvars )
17999  {
18000  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18001  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18002 
18003  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18004  assert(requiredsize <= nconsvars);
18005  }
18006 
18007  /* adjust sides and check that we do not subtract infinity values */
18008  if( SCIPisInfinity(scip, REALABS(constant)) )
18009  {
18010  if( constant < 0.0 )
18011  {
18012  if( SCIPisInfinity(scip, lhs) )
18013  {
18014  SCIPfreeBufferArray(scip, &consvals);
18015  SCIPfreeBufferArray(scip, &consvars);
18016 
18017  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);
18018 
18019  SCIPABORT();
18020  return SCIP_INVALIDDATA; /*lint !e527*/
18021  }
18022  if( SCIPisInfinity(scip, rhs) )
18023  {
18024  SCIPfreeBufferArray(scip, &consvals);
18025  SCIPfreeBufferArray(scip, &consvars);
18026 
18027  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);
18028 
18029  SCIPABORT();
18030  return SCIP_INVALIDDATA; /*lint !e527*/
18031  }
18032 
18033  lhs = -SCIPinfinity(scip);
18034  rhs = -SCIPinfinity(scip);
18035  }
18036  else
18037  {
18038  if( SCIPisInfinity(scip, -lhs) )
18039  {
18040  SCIPfreeBufferArray(scip, &consvals);
18041  SCIPfreeBufferArray(scip, &consvars);
18042 
18043  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);
18044 
18045  SCIPABORT();
18046  return SCIP_INVALIDDATA; /*lint !e527*/
18047  }
18048  if( SCIPisInfinity(scip, -rhs) )
18049  {
18050  SCIPfreeBufferArray(scip, &consvals);
18051  SCIPfreeBufferArray(scip, &consvars);
18052 
18053  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);
18054 
18055  SCIPABORT();
18056  return SCIP_INVALIDDATA; /*lint !e527*/
18057  }
18058 
18059  lhs = SCIPinfinity(scip);
18060  rhs = SCIPinfinity(scip);
18061  }
18062  }
18063  else
18064  {
18065  if( !SCIPisInfinity(scip, REALABS(lhs)) )
18066  lhs -= constant;
18067  if( !SCIPisInfinity(scip, REALABS(rhs)) )
18068  rhs -= constant;
18069 
18070  if( SCIPisInfinity(scip, -lhs) )
18071  lhs = -SCIPinfinity(scip);
18072  else if( SCIPisInfinity(scip, lhs) )
18073  lhs = SCIPinfinity(scip);
18074 
18075  if( SCIPisInfinity(scip, rhs) )
18076  rhs = SCIPinfinity(scip);
18077  else if( SCIPisInfinity(scip, -rhs) )
18078  rhs = -SCIPinfinity(scip);
18079  }
18080 
18081  /* create constraint data */
18082  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
18083  assert(consdata != NULL);
18084 
18085  SCIPfreeBufferArray(scip, &consvals);
18086  SCIPfreeBufferArray(scip, &consvars);
18087  }
18088  else
18089  {
18090  /* create constraint data */
18091  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18092  assert(consdata != NULL);
18093  }
18094 
18095 #ifndef NDEBUG
18096  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18097  if( check || enforce )
18098  {
18099  int n;
18100  for(n = consdata->nvars - 1; n >= 0; --n )
18101  assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18102  }
18103 #endif
18104 
18105  /* create constraint */
18106  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18107  local, modifiable, dynamic, removable, stickingatnode) );
18108 
18109  return SCIP_OKAY;
18110 }
18111 
18112 /** creates and captures a linear constraint
18113  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18114  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18115  *
18116  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18117  *
18118  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18119  */
18121  SCIP* scip, /**< SCIP data structure */
18122  SCIP_CONS** cons, /**< pointer to hold the created constraint */
18123  const char* name, /**< name of constraint */
18124  int nvars, /**< number of nonzeros in the constraint */
18125  SCIP_VAR** vars, /**< array with variables of constraint entries */
18126  SCIP_Real* vals, /**< array with coefficients of constraint entries */
18127  SCIP_Real lhs, /**< left hand side of constraint */
18128  SCIP_Real rhs /**< right hand side of constraint */
18129  )
18130 {
18131  assert(scip != NULL);
18132 
18133  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18134  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
18135 
18136  return SCIP_OKAY;
18137 }
18138 
18139 /** creates by copying and captures a linear constraint */
18141  SCIP* scip, /**< target SCIP data structure */
18142  SCIP_CONS** cons, /**< pointer to store the created target constraint */
18143  SCIP* sourcescip, /**< source SCIP data structure */
18144  const char* name, /**< name of constraint */
18145  int nvars, /**< number of variables in source variable array */
18146  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18147  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18148  SCIP_Real lhs, /**< left hand side of the linear constraint */
18149  SCIP_Real rhs, /**< right hand side of the linear constraint */
18150  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18151  * variables of the target SCIP */
18152  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18153  * target constraints */
18154  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18155  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18156  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18157  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18158  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18159  SCIP_Bool local, /**< is constraint only valid locally? */
18160  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18161  SCIP_Bool dynamic, /**< is constraint subject to aging? */
18162  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18163  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18164  * if it may be moved to a more global node? */
18165  SCIP_Bool global, /**< create a global or a local copy? */
18166  SCIP_Bool* valid /**< pointer to store if the copying was valid */
18167  )
18168 {
18169  SCIP_VAR** vars;
18170  SCIP_Real* coefs;
18171 
18172  SCIP_Real constant;
18173  int requiredsize;
18174  int v;
18175  SCIP_Bool success;
18176 
18177  if( SCIPisGT(scip, lhs, rhs) )
18178  {
18179  *valid = FALSE;
18180  return SCIP_OKAY;
18181  }
18182 
18183  (*valid) = TRUE;
18184 
18185  if( nvars == 0 )
18186  {
18187  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18188  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18189  return SCIP_OKAY;
18190  }
18191 
18192  /* duplicate variable array */
18193  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
18194 
18195  /* duplicate coefficient array */
18196  if( sourcecoefs != NULL )
18197  {
18198  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18199  }
18200  else
18201  {
18202  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18203  for( v = 0; v < nvars; ++v )
18204  coefs[v] = 1.0;
18205  }
18206 
18207  constant = 0.0;
18208 
18209  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18210  * the target SCIP
18211  */
18212  if( !SCIPvarIsOriginal(vars[0]) )
18213  {
18214  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18215 
18216  if( requiredsize > nvars )
18217  {
18218  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18219  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18220 
18221  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18222  assert(requiredsize <= nvars);
18223  }
18224  }
18225  else
18226  {
18227  for( v = 0; v < nvars; ++v )
18228  {
18229  assert(SCIPvarIsOriginal(vars[v]));
18230  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18231  assert(vars[v] != NULL);
18232  }
18233  }
18234 
18235  success = TRUE;
18236  /* map variables of the source constraint to variables of the target SCIP */
18237  for( v = 0; v < nvars && success; ++v )
18238  {
18239  SCIP_VAR* var;
18240  var = vars[v];
18241 
18242  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18243  assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18244 
18245  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18246  assert(!(success) || vars[v] != NULL);
18247  }
18248 
18249  /* only create the target constraint, if all variables could be copied */
18250  if( success )
18251  {
18252  if( !SCIPisInfinity(scip, -lhs) )
18253  lhs -= constant;
18254 
18255  if( !SCIPisInfinity(scip, rhs) )
18256  rhs -= constant;
18257 
18258  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18259  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18260  }
18261  else
18262  *valid = FALSE;
18263 
18264  /* free buffer array */
18265  SCIPfreeBufferArray(scip, &coefs);
18266  SCIPfreeBufferArray(scip, &vars);
18267 
18268  return SCIP_OKAY;
18269 }
18270 
18271 /** adds coefficient to linear constraint (if it is not zero) */
18273  SCIP* scip, /**< SCIP data structure */
18274  SCIP_CONS* cons, /**< constraint data */
18275  SCIP_VAR* var, /**< variable of constraint entry */
18276  SCIP_Real val /**< coefficient of constraint entry */
18277  )
18278 {
18279  assert(scip != NULL);
18280  assert(cons != NULL);
18281  assert(var != NULL);
18282 
18283  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18284  {
18285  SCIPerrorMessage("constraint is not linear\n");
18286  return SCIP_INVALIDDATA;
18287  }
18288 
18289  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18290  * constraint after presolving we have to ensure that it holds active variables
18291  */
18292  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
18293  {
18294  SCIP_CONSDATA* consdata;
18295  SCIP_VAR** consvars;
18296  SCIP_Real* consvals;
18297  SCIP_Real constant = 0.0;
18298  SCIP_Real rhs;
18299  SCIP_Real lhs;
18300  int nconsvars;
18301  int requiredsize;
18302  int v;
18303 
18304  nconsvars = 1;
18305  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18306  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18307  consvars[0] = var;
18308  consvals[0] = val;
18309 
18310  /* get active variables for new constraint */
18311  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18312 
18313  /* if space was not enough we need to resize the buffers */
18314  if( requiredsize > nconsvars )
18315  {
18316  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18317  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18318 
18319  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18320  assert(requiredsize <= nconsvars);
18321  }
18322 
18323  consdata = SCIPconsGetData(cons);
18324  assert(consdata != NULL);
18325 
18326  lhs = consdata->lhs;
18327  rhs = consdata->rhs;
18328 
18329  /* adjust sides and check that we do not subtract infinity values */
18330  /* constant is infinite */
18331  if( SCIPisInfinity(scip, REALABS(constant)) )
18332  {
18333  if( constant < 0.0 )
18334  {
18335  if( SCIPisInfinity(scip, lhs) )
18336  {
18337  SCIPfreeBufferArray(scip, &consvals);
18338  SCIPfreeBufferArray(scip, &consvars);
18339 
18340  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));
18341 
18342  SCIPABORT();
18343  return SCIP_INVALIDDATA; /*lint !e527*/
18344  }
18345  if( SCIPisInfinity(scip, rhs) )
18346  {
18347  SCIPfreeBufferArray(scip, &consvals);
18348  SCIPfreeBufferArray(scip, &consvars);
18349 
18350  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));
18351 
18352  SCIPABORT();
18353  return SCIP_INVALIDDATA; /*lint !e527*/
18354  }
18355 
18356  lhs = -SCIPinfinity(scip);
18357  rhs = -SCIPinfinity(scip);
18358  }
18359  else
18360  {
18361  if( SCIPisInfinity(scip, -lhs) )
18362  {
18363  SCIPfreeBufferArray(scip, &consvals);
18364  SCIPfreeBufferArray(scip, &consvars);
18365 
18366  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));
18367 
18368  SCIPABORT();
18369  return SCIP_INVALIDDATA; /*lint !e527*/
18370  }
18371  if( SCIPisInfinity(scip, -rhs) )
18372  {
18373  SCIPfreeBufferArray(scip, &consvals);
18374  SCIPfreeBufferArray(scip, &consvars);
18375 
18376  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));
18377 
18378  SCIPABORT();
18379  return SCIP_INVALIDDATA; /*lint !e527*/
18380  }
18381 
18382  lhs = SCIPinfinity(scip);
18383  rhs = SCIPinfinity(scip);
18384  }
18385  }
18386  /* constant is not infinite */
18387  else
18388  {
18389  if( !SCIPisInfinity(scip, REALABS(lhs)) )
18390  lhs -= constant;
18391  if( !SCIPisInfinity(scip, REALABS(rhs)) )
18392  rhs -= constant;
18393 
18394  if( SCIPisInfinity(scip, -lhs) )
18395  lhs = -SCIPinfinity(scip);
18396  else if( SCIPisInfinity(scip, lhs) )
18397  lhs = SCIPinfinity(scip);
18398 
18399  if( SCIPisInfinity(scip, rhs) )
18400  rhs = SCIPinfinity(scip);
18401  else if( SCIPisInfinity(scip, -rhs) )
18402  rhs = -SCIPinfinity(scip);
18403  }
18404 
18405  /* add all active variables to constraint */
18406  for( v = nconsvars - 1; v >= 0; --v )
18407  {
18408  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18409  }
18410 
18411  /* update left and right hand sides */
18412  SCIP_CALL( chgLhs(scip, cons, lhs));
18413  SCIP_CALL( chgRhs(scip, cons, rhs));
18414 
18415  SCIPfreeBufferArray(scip, &consvals);
18416  SCIPfreeBufferArray(scip, &consvars);
18417  }
18418  else
18419  {
18420  SCIP_CALL( addCoef(scip, cons, var, val) );
18421  }
18422 
18423  return SCIP_OKAY;
18424 }
18425 
18426 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18427  * not yet contained in the constraint
18428  *
18429  * @note This method may only be called during problem creation stage for an original constraint and variable.
18430  *
18431  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18432  */
18434  SCIP* scip, /**< SCIP data structure */
18435  SCIP_CONS* cons, /**< constraint data */
18436  SCIP_VAR* var, /**< variable of constraint entry */
18437  SCIP_Real val /**< new coefficient of constraint entry */
18438  )
18439 {
18440  SCIP_CONSDATA* consdata;
18441  SCIP_VAR** vars;
18442  SCIP_Bool found;
18443  int i;
18444 
18445  assert(scip != NULL);
18446  assert(cons != NULL);
18447  assert(var != NULL);
18448 
18449  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18450  {
18451  SCIPerrorMessage("constraint is not linear\n");
18453  }
18454 
18455  if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
18456  {
18457  SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18458  return SCIP_INVALIDDATA;
18459  }
18460 
18461  consdata = SCIPconsGetData(cons);
18462  assert(consdata != NULL);
18463 
18464  vars = consdata->vars;
18465  found = FALSE;
18466  i = 0;
18467  while( i < consdata->nvars )
18468  {
18469  if( vars[i] == var )
18470  {
18471  if( found || SCIPisZero(scip, val) )
18472  {
18473  SCIP_CALL( delCoefPos(scip, cons, i) );
18474 
18475  /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18476  i--;
18477  }
18478  else
18479  {
18480  SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18481  }
18482  found = TRUE;
18483  }
18484  i++;
18485  }
18486 
18487  if( !found && !SCIPisZero(scip, val) )
18488  {
18489  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18490  }
18491 
18492  return SCIP_OKAY;
18493 }
18494 
18495 /** deletes variable from linear constraint
18496  *
18497  * @note This method may only be called during problem creation stage for an original constraint and variable.
18498  *
18499  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18500  */
18502  SCIP* scip, /**< SCIP data structure */
18503  SCIP_CONS* cons, /**< constraint data */
18504  SCIP_VAR* var /**< variable of constraint entry */
18505  )
18506 {
18507  assert(scip != NULL);
18508  assert(cons != NULL);
18509  assert(var != NULL);
18510 
18511  SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18512 
18513  return SCIP_OKAY;
18514 }
18515 
18516 /** gets left hand side of linear constraint */
18518  SCIP* scip, /**< SCIP data structure */
18519  SCIP_CONS* cons /**< constraint data */
18520  )
18521 {
18522  SCIP_CONSDATA* consdata;
18523 
18524  assert(scip != NULL);
18525  assert(cons != NULL);
18526 
18527  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18528  {
18529  SCIPerrorMessage("constraint is not linear\n");
18530  SCIPABORT();
18531  return SCIP_INVALID; /*lint !e527*/
18532  }
18533 
18534  consdata = SCIPconsGetData(cons);
18535  assert(consdata != NULL);
18537  return consdata->lhs;
18538 }
18539 
18540 /** gets right hand side of linear constraint */
18542  SCIP* scip, /**< SCIP data structure */
18543  SCIP_CONS* cons /**< constraint data */
18544  )
18545 {
18546  SCIP_CONSDATA* consdata;
18547 
18548  assert(scip != NULL);
18549  assert(cons != NULL);
18550 
18551  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18552  {
18553  SCIPerrorMessage("constraint is not linear\n");
18554  SCIPABORT();
18555  return SCIP_INVALID; /*lint !e527*/
18556  }
18557 
18558  consdata = SCIPconsGetData(cons);
18559  assert(consdata != NULL);
18561  return consdata->rhs;
18562 }
18563 
18564 /** changes left hand side of linear constraint */
18566  SCIP* scip, /**< SCIP data structure */
18567  SCIP_CONS* cons, /**< constraint data */
18568  SCIP_Real lhs /**< new left hand side */
18569  )
18570 {
18571  assert(scip != NULL);
18572  assert(cons != NULL);
18573 
18574  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18575  {
18576  SCIPerrorMessage("constraint is not linear\n");
18577  return SCIP_INVALIDDATA;
18578  }
18579 
18580  SCIP_CALL( chgLhs(scip, cons, lhs) );
18581 
18582  return SCIP_OKAY;
18583 }
18585 /** changes right hand side of linear constraint */
18587  SCIP* scip, /**< SCIP data structure */
18588  SCIP_CONS* cons, /**< constraint data */
18589  SCIP_Real rhs /**< new right hand side */
18590  )
18591 {
18592  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18593  {
18594  SCIPerrorMessage("constraint is not linear\n");
18595  return SCIP_INVALIDDATA;
18596  }
18597 
18598  SCIP_CALL( chgRhs(scip, cons, rhs) );
18599 
18600  return SCIP_OKAY;
18601 }
18602 
18603 /** gets the number of variables in the linear constraint */
18604 int SCIPgetNVarsLinear(
18605  SCIP* scip, /**< SCIP data structure */
18606  SCIP_CONS* cons /**< constraint data */
18607  )
18608 {
18609  SCIP_CONSDATA* consdata;
18610 
18611  assert(scip != NULL);
18612  assert(cons != NULL);
18613 
18614  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18615  {
18616  SCIPerrorMessage("constraint is not linear\n");
18617  SCIPABORT();
18618  return -1; /*lint !e527*/
18619  }
18620 
18621  consdata = SCIPconsGetData(cons);
18622  assert(consdata != NULL);
18624  return consdata->nvars;
18625 }
18626 
18627 /** gets the array of variables in the linear constraint; the user must not modify this array! */
18629  SCIP* scip, /**< SCIP data structure */
18630  SCIP_CONS* cons /**< constraint data */
18631  )
18632 {
18633  SCIP_CONSDATA* consdata;
18634 
18635  assert(scip != NULL);
18636  assert(cons != NULL);
18637 
18638  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18639  {
18640  SCIPerrorMessage("constraint is not linear\n");
18641  SCIPABORT();
18642  return NULL; /*lint !e527*/
18643  }
18644 
18645  consdata = SCIPconsGetData(cons);
18646  assert(consdata != NULL);
18648  return consdata->vars;
18649 }
18650 
18651 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18653  SCIP* scip, /**< SCIP data structure */
18654  SCIP_CONS* cons /**< constraint data */
18655  )
18656 {
18657  SCIP_CONSDATA* consdata;
18658 
18659  assert(scip != NULL);
18660  assert(cons != NULL);
18661 
18662  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18663  {
18664  SCIPerrorMessage("constraint is not linear\n");
18665  SCIPABORT();
18666  return NULL; /*lint !e527*/
18667  }
18668 
18669  consdata = SCIPconsGetData(cons);
18670  assert(consdata != NULL);
18672  return consdata->vals;
18673 }
18674 
18675 /** gets the activity of the linear constraint in the given solution
18676  *
18677  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18678  * comprises positive and negative infinity contributions
18679  */
18681  SCIP* scip, /**< SCIP data structure */
18682  SCIP_CONS* cons, /**< constraint data */
18683  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18684  )
18685 {
18686  SCIP_CONSDATA* consdata;
18687 
18688  assert(scip != NULL);
18689  assert(cons != NULL);
18690 
18691  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18692  {
18693  SCIPerrorMessage("constraint is not linear\n");
18694  SCIPABORT();
18695  return SCIP_INVALID; /*lint !e527*/
18696  }
18697 
18698  consdata = SCIPconsGetData(cons);
18699  assert(consdata != NULL);
18700 
18701  if( consdata->row != NULL )
18702  return SCIPgetRowSolActivity(scip, consdata->row, sol);
18703  else
18704  return consdataGetActivity(scip, consdata, sol);
18705 }
18706 
18707 /** gets the feasibility of the linear constraint in the given solution */
18709  SCIP* scip, /**< SCIP data structure */
18710  SCIP_CONS* cons, /**< constraint data */
18711  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18712  )
18713 {
18714  SCIP_CONSDATA* consdata;
18715 
18716  assert(scip != NULL);
18717  assert(cons != NULL);
18718 
18719  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18720  {
18721  SCIPerrorMessage("constraint is not linear\n");
18722  SCIPABORT();
18723  return SCIP_INVALID; /*lint !e527*/
18724  }
18725 
18726  consdata = SCIPconsGetData(cons);
18727  assert(consdata != NULL);
18728 
18729  if( consdata->row != NULL )
18730  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18731  else
18732  return consdataGetFeasibility(scip, consdata, sol);
18733 }
18734 
18735 /** gets the dual solution of the linear constraint in the current LP */
18737  SCIP* scip, /**< SCIP data structure */
18738  SCIP_CONS* cons /**< constraint data */
18739  )
18740 {
18741  SCIP_CONSDATA* consdata;
18742 
18743  assert(scip != NULL);
18744  assert(cons != NULL);
18745  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18746 
18747  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18748  {
18749  SCIPerrorMessage("constraint is not linear\n");
18750  SCIPABORT();
18751  return SCIP_INVALID; /*lint !e527*/
18752  }
18753 
18754  consdata = SCIPconsGetData(cons);
18755  assert(consdata != NULL);
18756 
18757  if( consdata->row != NULL )
18758  return SCIProwGetDualsol(consdata->row);
18759  else
18760  return 0.0;
18761 }
18762 
18763 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18765  SCIP* scip, /**< SCIP data structure */
18766  SCIP_CONS* cons /**< constraint data */
18767  )
18768 {
18769  SCIP_CONSDATA* consdata;
18770 
18771  assert(scip != NULL);
18772  assert(cons != NULL);
18773  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18774 
18775  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18776  {
18777  SCIPerrorMessage("constraint is not linear\n");
18778  SCIPABORT();
18779  return SCIP_INVALID; /*lint !e527*/
18780  }
18781 
18782  consdata = SCIPconsGetData(cons);
18783  assert(consdata != NULL);
18784 
18785  if( consdata->row != NULL )
18786  return SCIProwGetDualfarkas(consdata->row);
18787  else
18788  return 0.0;
18789 }
18790 
18791 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18792  * the user must not modify the row!
18793  */
18795  SCIP* scip, /**< SCIP data structure */
18796  SCIP_CONS* cons /**< constraint data */
18797  )
18798 {
18799  SCIP_CONSDATA* consdata;
18800 
18801  assert(scip != NULL);
18802  assert(cons != NULL);
18803 
18804  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18805  {
18806  SCIPerrorMessage("constraint is not linear\n");
18807  SCIPABORT();
18808  return NULL; /*lint !e527*/
18809  }
18810 
18811  consdata = SCIPconsGetData(cons);
18812  assert(consdata != NULL);
18814  return consdata->row;
18815 }
18816 
18817 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18819  SCIP* scip, /**< SCIP data structure */
18820  SCIP_CONS* cons, /**< source constraint to try to convert */
18821  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18822  )
18823 {
18824  SCIP_CONSHDLR* conshdlr;
18825  SCIP_CONSHDLRDATA* conshdlrdata;
18826  SCIP_CONSDATA* consdata;
18827  SCIP_VAR* var;
18828  SCIP_Real val;
18829  SCIP_Real lb;
18830  SCIP_Real ub;
18831  SCIP_Real poscoeffsum;
18832  SCIP_Real negcoeffsum;
18833  SCIP_Bool infeasible;
18834  SCIP_Bool integral;
18835  int nchgsides = 0;
18836  int nposbin;
18837  int nnegbin;
18838  int nposint;
18839  int nnegint;
18840  int nposimpl;
18841  int nnegimpl;
18842  int nposimplbin;
18843  int nnegimplbin;
18844  int nposcont;
18845  int nnegcont;
18846  int ncoeffspone;
18847  int ncoeffsnone;
18848  int ncoeffspint;
18849  int ncoeffsnint;
18850  int ncoeffspfrac;
18851  int ncoeffsnfrac;
18852  int i;
18853 
18854  assert(scip != NULL);
18855  assert(cons != NULL);
18856  assert(upgdcons != NULL);
18857 
18858  *upgdcons = NULL;
18859 
18860  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18861  if( SCIPconsIsModifiable(cons) )
18862  return SCIP_OKAY;
18863 
18864  /* check for upgradability */
18865  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18866  return SCIP_OKAY;
18867 
18868  /* get the constraint handler and check, if it's really a linear constraint */
18869  conshdlr = SCIPconsGetHdlr(cons);
18870  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18871  {
18872  SCIPerrorMessage("constraint is not linear\n");
18873  return SCIP_INVALIDDATA;
18874  }
18875 
18876  /* get constraint handler data and constraint data */
18877  conshdlrdata = SCIPconshdlrGetData(conshdlr);
18878  assert(conshdlrdata != NULL);
18879  consdata = SCIPconsGetData(cons);
18880  assert(consdata != NULL);
18881 
18882  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18883  if( consdata->upgraded )
18884  return SCIP_OKAY;
18885 
18886  /* check, if the constraint is already stored as LP row */
18887  if( consdata->row != NULL )
18888  {
18889  if( SCIProwIsInLP(consdata->row) )
18890  {
18891  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18892  return SCIP_INVALIDDATA;
18893  }
18894  else
18895  {
18896  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18897  }
18898  }
18899 
18900  /* normalize constraint */
18901  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18902 
18903  /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18904  * skipped and we hope that the infeasibility gets detected later again.
18905  *
18906  * TODO: do we want to try to upgrade the constraint anyway?
18907  *
18908  * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18909  * proven to be infeasible.
18910  */
18911  if( infeasible ) /*lint !e774*/
18912  return SCIP_OKAY;
18913 
18914  /* tighten sides */
18915  SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18916 
18917  if( infeasible ) /*lint !e774*/
18918  return SCIP_OKAY;
18919 
18920  /*
18921  * calculate some statistics on linear constraint
18922  */
18923 
18924  nposbin = 0;
18925  nnegbin = 0;
18926  nposint = 0;
18927  nnegint = 0;
18928  nposimpl = 0;
18929  nnegimpl = 0;
18930  nposimplbin = 0;
18931  nnegimplbin = 0;
18932  nposcont = 0;
18933  nnegcont = 0;
18934  ncoeffspone = 0;
18935  ncoeffsnone = 0;
18936  ncoeffspint = 0;
18937  ncoeffsnint = 0;
18938  ncoeffspfrac = 0;
18939  ncoeffsnfrac = 0;
18940  integral = TRUE;
18941  poscoeffsum = 0.0;
18942  negcoeffsum = 0.0;
18943 
18944  for( i = 0; i < consdata->nvars; ++i )
18945  {
18946  var = consdata->vars[i];
18947  val = consdata->vals[i];
18948  lb = SCIPvarGetLbLocal(var);
18949  ub = SCIPvarGetUbLocal(var);
18950  assert(!SCIPisZero(scip, val));
18951 
18952  switch( SCIPvarGetType(var) )
18953  {
18954  case SCIP_VARTYPE_BINARY:
18955  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18956  integral = integral && SCIPisIntegral(scip, val);
18957  if( val >= 0.0 )
18958  nposbin++;
18959  else
18960  nnegbin++;
18961  break;
18962  case SCIP_VARTYPE_INTEGER:
18963  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18964  integral = integral && SCIPisIntegral(scip, val);
18965  if( val >= 0.0 )
18966  nposint++;
18967  else
18968  nnegint++;
18969  break;
18970  case SCIP_VARTYPE_IMPLINT:
18971  if( SCIPvarIsBinary(var) )
18972  {
18973  if( val >= 0.0 )
18974  nposimplbin++;
18975  else
18976  nnegimplbin++;
18977  }
18978  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18979  integral = integral && SCIPisIntegral(scip, val);
18980  if( val >= 0.0 )
18981  nposimpl++;
18982  else
18983  nnegimpl++;
18984  break;
18986  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18987  if( val >= 0.0 )
18988  nposcont++;
18989  else
18990  nnegcont++;
18991  break;
18992  default:
18993  SCIPerrorMessage("unknown variable type\n");
18994  return SCIP_INVALIDDATA;
18995  }
18996  if( SCIPisEQ(scip, val, 1.0) )
18997  ncoeffspone++;
18998  else if( SCIPisEQ(scip, val, -1.0) )
18999  ncoeffsnone++;
19000  else if( SCIPisIntegral(scip, val) )
19001  {
19002  if( SCIPisPositive(scip, val) )
19003  ncoeffspint++;
19004  else
19005  ncoeffsnint++;
19006  }
19007  else
19008  {
19009  if( SCIPisPositive(scip, val) )
19010  ncoeffspfrac++;
19011  else
19012  ncoeffsnfrac++;
19013  }
19014  if( SCIPisPositive(scip, val) )
19015  poscoeffsum += val;
19016  else
19017  negcoeffsum += val;
19018  }
19019 
19020  /*
19021  * call the upgrading methods
19022  */
19023 
19024  SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
19025  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
19026  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",
19027  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
19028  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
19029  poscoeffsum, negcoeffsum, integral);
19030 
19031  /* try all upgrading methods in priority order in case the upgrading step is enable */
19032  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
19033  {
19034  if( conshdlrdata->linconsupgrades[i]->active )
19035  {
19036  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
19037  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
19038  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
19039  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
19040  poscoeffsum, negcoeffsum, integral,
19041  upgdcons) );
19042  }
19043  }
19044 
19045 #ifdef SCIP_DEBUG
19046  if( *upgdcons != NULL )
19047  {
19048  SCIPdebugPrintCons(scip, cons, NULL);
19049  SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
19050  SCIPdebugPrintCons(scip, *upgdcons, NULL);
19051  }
19052 #endif
19053 
19054  return SCIP_OKAY; /*lint !e438*/
19055 }
19056 
19057 /** cleans up (multi-)aggregations and fixings from linear constraints */
19059  SCIP* scip, /**< SCIP data structure */
19060  SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
19061  SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
19062  )
19063 {
19064  SCIP_CONSHDLR* conshdlr;
19065  SCIP_CONS** conss;
19066  int nconss;
19067  int i;
19068 
19069  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
19070  if( conshdlr == NULL )
19071  return SCIP_OKAY;
19072 
19073  assert(infeasible != NULL);
19074  *infeasible = FALSE;
19075 
19076  nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
19077  conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
19078 
19079  for( i = 0; i < nconss; ++i )
19080  {
19081  SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
19082 
19083  if( *infeasible )
19084  break;
19085  }
19086 
19087  return SCIP_OKAY;
19088 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
#define EVENTHDLR_DESC
Definition: cons_linear.c:115
#define CONSHDLR_DELAYSEPA
Definition: cons_linear.c:107
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:4229
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
struct InferInfo INFERINFO
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1785
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:1695
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition: type_cons.h:91
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:578
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:6819
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1464
static SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
#define NULL
Definition: def.h:267
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
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:873
static int inferInfoGetPos(INFERINFO inferinfo)
Definition: cons_linear.c:424
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:737
#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:4042
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10866
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:5205
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3184
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2130
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
public methods for SCIP parameter handling
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3296
#define DEFAULT_MAXAGGRNORMSCALE
Definition: cons_linear.c:138
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:380
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_linear.c:126
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:72
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8475
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17871
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:601
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:96
#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:1994
#define CONSHDLR_MAXPREROUNDS
Definition: cons_linear.c:106
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:3205
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2547
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:1631
public methods for memory management
#define DEFAULT_RANGEDROWFREQ
Definition: cons_linear.c:173
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1569
#define MAXSCALEDCOEF
Definition: cons_linear.c:183
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:941
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define DEFAULT_CHECKRELMAXABS
Definition: cons_linear.c:135
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:3854
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:7890
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18681
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
#define DEFAULT_MAXROUNDS
Definition: cons_linear.c:122
#define DEFAULT_SORTVARS
Definition: cons_linear.c:132
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9551
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:5429
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18079
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:831
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:288
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3354
SCIP_RETCODE SCIPcleanupConssLinear(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible)
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17621
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:323
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1813
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:842
void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
Definition: cons.c:8110
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2843
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17859
static long bound
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1701
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip_cons.c:1372
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:2096
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18135
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1567
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:693
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:2325
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
Definition: cons_linear.c:527
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:124
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:1441
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip_cons.c:1525
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1250
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17600
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1332
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4273
#define SCIP_EVENTTYPE_TYPECHANGED
Definition: type_event.h:86
#define DEFAULT_DETECTPARTIALOBJECTIVE
Definition: cons_linear.c:167
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip_copy.c:2068
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define NLOCKTYPES
Definition: type_var.h:94
static void consdataGetGlbActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *glbminactivity, SCIP_Real *glbmaxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2902
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3359
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4595
#define DEFAULT_AGGREGATEVARIABLES
Definition: cons_linear.c:150
#define FALSE
Definition: def.h:94
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip_var.c:4647
static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1233
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:8226
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:324
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11184
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:181
static SCIP_DECL_CONSCOPY(consCopyLinear)
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10877
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:2964
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
Definition: cons_linear.c:608
#define TRUE
Definition: def.h:93
#define SCIPdebug(x)
Definition: pub_message.h:93
#define DEFAULT_MAXCARDBOUNDDIST
Definition: cons_linear.c:144
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2043
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:3585
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17916
#define DEFAULT_NMINCOMPARISONS
Definition: cons_linear.c:128
#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:8495
#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:7652
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)
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17769
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:75
static SCIP_DECL_CONSENFOPS(consEnfopsLinear)
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition: cons.c:8078
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17823
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8525
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:5322
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPdebugMessage
Definition: pub_message.h:96
#define DEFAULT_MINGAINPERNMINCOMP
Definition: cons_linear.c:129
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:235
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9824
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8575
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:88
static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3088
enum Proprule PROPRULE
Definition: cons_linear.c:374
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:433
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
Definition: cons_linear.c:5834
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip_var.c:4615
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17631
#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:590
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:776
public methods for SCIP variables
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip_cons.c:762
#define checkMaxActivityDelta(scip, consdata)
Definition: cons_linear.c:1564
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17905
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8485
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:125
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
Definition: cons_linear.c:3250
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:624
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17312
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
#define SCIPdebugMsgPrint
Definition: scip_message.h:79
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:83
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2341
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1482
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:808
#define DEFAULT_SEPARATEALL
Definition: cons_linear.c:147
SCIP_VAR ** x
Definition: circlepacking.c:63
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8277
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
Definition: cons_linear.c:8995
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:125
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2172
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
Definition: cons_linear.c:5098
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:998
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:111
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:112
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:2296
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8515
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:101
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17895
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17523
#define MAXCONSPRESOLROUNDS
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4261
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:9394
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:548
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip_cons.c:1297
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8178
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:5307
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:7269
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:6923
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:3864
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18089
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip_cons.c:444
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:117
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:8537
public methods for managing constraints
Constraint handler for knapsack constraints of the form , x binary and .
#define DEFAULT_DETECTCUTOFFBOUND
Definition: cons_linear.c:157
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1242
methods for dealing with symmetry detection graphs
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip_general.c:627
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition: nlp.c:1956
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8555
static SCIP_DECL_CONSDELETE(consDeleteLinear)
#define CONFLICTHDLR_PRIORITY
Definition: cons_linear.c:119
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:347
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:1552
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:5359
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:2522
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:100
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIPerrorMessage
Definition: pub_message.h:64
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4199
SCIP_VARTYPE SCIPeventGetOldtype(SCIP_EVENT *event)
Definition: event.c:1266
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
#define CONSHDLR_PROPFREQ
Definition: cons_linear.c:102
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3393
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:396
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8600
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3474
public methods for event handler plugins and event handlers
SCIP_RETCODE SCIPinferVarFixCons(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5434
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:416
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
Definition: scip_cons.c:900
#define COPYSIGN
Definition: def.h:258
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:1058
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip_var.c:1796
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1440
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:6782
static INLINE uint32_t SCIPrealHashCode(double x)
Definition: pub_misc.h:576
#define DEFAULT_MULTAGGRREMOVE
Definition: cons_linear.c:175
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
Definition: cons_linear.c:3628
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:467
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:2169
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3435
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4439
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition: scip_cons.c:1347
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2119
static int inferInfoGetProprule(INFERINFO inferinfo)
Definition: cons_linear.c:415
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:9117
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8216
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17835
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8435
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:17420
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:372
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4219
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:5163
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2015
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3921
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:5214
static int getInferInt(PROPRULE proprule, int pos)
Definition: cons_linear.c:452
#define SCIPhashSeven(a, b, c, d, e, f, g)
Definition: pub_misc.h:567
structs for symmetry computations
#define REALABS(x)
Definition: def.h:197
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:638
#define CONSHDLR_DELAYPROP
Definition: cons_linear.c:108
public methods for problem copies
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8565
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5142
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1453
#define SCIP_CALL(x)
Definition: def.h:380
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:2621
enum Proprule PROPRULE
Definition: cons_and.c:180
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define CONSHDLR_CHECKPRIORITY
Definition: cons_linear.c:100
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5499
#define SCIPhashSignature64(a)
Definition: pub_misc.h:549
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip_var.c:1740
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17883
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17707
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2677
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:141
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:2421
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:8455
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
Definition: cons_linear.c:4121
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:250
SCIP_RETCODE SCIPextendPermsymDetectionGraphLinear(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool *success)
static SCIP_DECL_CONSINIT(consInitLinear)
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:647
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:299
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
static SCIP_DECL_CONSTRANS(consTransLinear)
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17411
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:123
static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:83
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:122
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4638
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:7742
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:2226
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:162
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:4515
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linear.c:1122
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17549
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2804
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:3502
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:91
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1607
#define CONSHDLR_NEEDSCONS
Definition: cons_linear.c:109
#define CONSHDLR_EAGERFREQ
Definition: cons_linear.c:103
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:4214
static const char * paramname[]
Definition: lpi_msk.c:5096
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1413
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3116
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:670
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:7087
constraint handler for nonlinear constraints specified by algebraic expressions
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linear.c:586
#define DEFAULT_SINGLEVARSTUFFING
Definition: cons_linear.c:154
static SCIP_DECL_CONSPROP(consPropLinear)
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2537
#define DEFAULT_DUALPRESOLVING
Definition: cons_linear.c:152
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4585
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7553
static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8236
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11943
#define MIN(x, y)
Definition: def.h:243
methods for debugging
public methods for LP management
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8345
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2579
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:8415
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2073
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8385
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17927
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1279
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:18671
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2359
#define NONLINCONSUPGD_PRIORITY
Definition: cons_linear.c:199
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17811
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:954
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8278
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
int SCIPgetNRuns(SCIP *scip)
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17325
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4353
enum SYM_Symtype SYM_SYMTYPE
Definition: type_symmetry.h:60
#define MAXDNOM
Definition: cons_linear.c:182
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:785
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:79
Constraint handler for linear constraints in their most general form, .
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2220
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2608
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17847
SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2144
#define DEFAULT_MAXROUNDSROOT
Definition: cons_linear.c:123
#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:12775
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:5503
SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
#define DEFAULT_TIGHTENBOUNDSFREQ
Definition: cons_linear.c:121
#define SCIP_MAXTREEDEPTH
Definition: def.h:316
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4672
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
Definition: scip_cons.c:924
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:151
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7529
#define MINVALRECOMP
Definition: cons_linear.c:196
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2346
#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:98
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8667
#define SCIP_REAL_MAX
Definition: def.h:174
SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:424
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
Definition: cons_linear.c:2670
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1359
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip_var.c:343
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip_prob.c:3696
static SCIP_Bool canTightenBounds(SCIP_CONS *cons)
Definition: cons_linear.c:5331
static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
static SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
#define MAXSCALEDCOEFINTEGER
Definition: cons_linear.c:184
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:8609
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
#define SCIP_LONGINT_FORMAT
Definition: def.h:165
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:516
#define EPSGT(x, y, eps)
Definition: def.h:201
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:562
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:3230
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:5776
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:670
general public methods
#define MAX(x, y)
Definition: def.h:239
static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5538
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:2751
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
public methods for solutions
static const SCIP_Real scalars[]
Definition: lp.c:5743
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip_copy.c:711
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1668
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8246
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:5617
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip_cons.c:396
#define CONTWEIGHT
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4615
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:1322
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1493
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:810
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip_cons.c:420
static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:152
public methods for conflict analysis handlers
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3042
static SCIP_RETCODE extractCliques(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, int *nfixedvars, int *nchgbds, SCIP_Bool *cutoff)
Definition: cons_linear.c:8025
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:1174
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)
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:540
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:1431
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:9607
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:118
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17539
SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
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:8403
#define DEFAULT_MAXDUALMULTAGGRQUOT
Definition: cons_linear.c:179
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1216
#define SCIP_Real
Definition: def.h:173
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:7091
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8465
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_lp.c:1727
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:718
#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:9665
#define DEFAULT_SINGLETONSTUFFING
Definition: cons_linear.c:153
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:854
#define EVENTHDLR_NAME
Definition: cons_linear.c:114
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
#define CONSHDLR_ENFOPRIORITY
Definition: cons_linear.c:99
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:4656
int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4658
public methods for message handling
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
Definition: cons_linear.c:1161
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8405
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip_var.c:8567
static unsigned int getParallelConsKey(SCIP_CONS *cons)
#define SCIP_INVALID
Definition: def.h:193
#define DEFAULT_RANGEDROWPROPAGATION
Definition: cons_linear.c:170
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8395
Proprule
Definition: cons_and.c:172
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2212
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3756
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
#define CONSHDLR_DESC
Definition: cons_linear.c:97
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
#define SCIP_Longint
Definition: def.h:158
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18191
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17759
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2167
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_linear.c:492
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:298
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17585
static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
#define MAX_CLIQUE_NONZEROS_PER_CONS
Definition: cons_linear.c:7958
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1386
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9719
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:18145
#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:17562
static int inferInfoToInt(INFERINFO inferinfo)
Definition: cons_linear.c:406
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8425
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
#define MAXVALRECOMP
Definition: cons_linear.c:195
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:703
static SCIP_DECL_CONSPRESOL(consPresolLinear)
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip_cons.c:670
#define DEFAULT_MAXEASYACTIVITYDELTA
Definition: cons_linear.c:141
#define QUAD_MEMBER(x)
Definition: dbldblarith.h:48
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define DEFAULT_EXTRACTCLIQUES
Definition: cons_linear.c:180
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:76
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3228
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
#define SCIP_CALL_ABORT(x)
Definition: def.h:359
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:172
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip_cons.c:468
#define SCIPABORT()
Definition: def.h:352
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:17611
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9121
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1217
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17641
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:393
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1268
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
#define MAXACTVAL
Definition: cons_linear.c:189
#define INTWEIGHT
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition: scip_var.c:8631
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:4916
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9373
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
#define ABS(x)
Definition: def.h:235
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7616
#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:2023
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:178
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:127
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17749
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17575
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:2048
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linear.c:1081
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:281
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip_cons.c:1272
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:124
memory allocation routines
#define DEFAULT_RANGEDROWARTCONS
Definition: cons_linear.c:171