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* istight, /**< pointer to store whether activity bound is tight to variable bounds
2415  * i.e. is the actual minactivity (otherwise a lower bound is provided) */
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(istight != NULL);
2427  assert(issettoinfinity != NULL);
2428 
2429  /* if we have neg. infinite contributions, the minactivity is -infty */
2430  if( neginf > 0 )
2431  {
2432  *minactivity = -SCIPinfinity(scip);
2433  *issettoinfinity = TRUE;
2434  *istight = posinf == 0;
2435  }
2436  /* if we have pos. (and no neg.) infinite contributions, the minactivity is +infty */
2437  else if( posinf > 0 )
2438  {
2439  *minactivity = SCIPinfinity(scip);
2440  *issettoinfinity = TRUE;
2441  *istight = TRUE;
2442  }
2443  /* if we have neg. huge contributions or do not need a good relaxation, we just return -infty as minactivity */
2444  else if( neghuge > 0 || ( poshuge > 0 && !goodrelax ) )
2445  {
2446  *minactivity = -SCIPinfinity(scip);
2447  *issettoinfinity = TRUE;
2448  *istight = FALSE;
2449  }
2450  else
2451  {
2452  SCIP_Real QUAD(tmpactivity);
2453 
2454  /* recompute minactivity if it is not valid */
2455  if( global )
2456  {
2457  if( !consdata->validglbminact )
2458  consdataRecomputeGlbMinactivity(scip, consdata);
2459  assert(consdata->validglbminact);
2460 
2461  QUAD_ASSIGN_Q(tmpactivity, consdata->glbminactivity);
2462  }
2463  else
2464  {
2465  if( !consdata->validminact )
2466  consdataRecomputeMinactivity(scip, consdata);
2467  assert(consdata->validminact);
2468 
2469  QUAD_ASSIGN_Q(tmpactivity, consdata->minactivity);
2470  }
2471 
2472  /* calculate residual minactivity */
2473  SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
2474 
2475  /* we have no infinite and no neg. huge contributions, but pos. huge contributions; a feasible relaxation of the
2476  * minactivity is given by adding the number of positive huge contributions times the huge value
2477  */
2478  if( poshuge > 0 )
2479  {
2480  SCIPquadprecSumQD(tmpactivity, tmpactivity, poshuge * SCIPgetHugeValue(scip));
2481  *istight = FALSE;
2482  }
2483  /* all counters are zero, so the minactivity is tight */
2484  else
2485  *istight = TRUE;
2486 
2487  /* round residual minactivity */
2488  *minactivity = QUAD_TO_DBL(tmpactivity);
2489  *issettoinfinity = FALSE;
2490  }
2491 }
2492 
2493 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2494  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2495  */
2496 static
2497 void getMaxActivity(
2498  SCIP* scip, /**< SCIP data structure */
2499  SCIP_CONSDATA* consdata, /**< linear constraint */
2500  int posinf, /**< number of coefficients contributing pos. infinite value */
2501  int neginf, /**< number of coefficients contributing neg. infinite value */
2502  int poshuge, /**< number of coefficients contributing huge pos. value */
2503  int neghuge, /**< number of coefficients contributing huge neg. value */
2504  SCIP_Real delta, /**< value to subtract from stored maxactivity
2505  * (contribution of the variable set to zero when getting residual activity) */
2506  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2507  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2508  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2509  SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
2510  * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2511  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2512  )
2513 {
2514  assert(scip != NULL);
2515  assert(consdata != NULL);
2516  assert(posinf >= 0);
2517  assert(neginf >= 0);
2518  assert(poshuge >= 0);
2519  assert(neghuge >= 0);
2520  assert(maxactivity != NULL);
2521  assert(istight != NULL);
2522  assert(issettoinfinity != NULL);
2523 
2524  /* if we have pos. infinite contributions, the maxactivity is +infty */
2525  if( posinf > 0 )
2526  {
2527  *maxactivity = SCIPinfinity(scip);
2528  *issettoinfinity = TRUE;
2529  *istight = neginf == 0;
2530  }
2531  /* if we have neg. (and no pos.) infinite contributions, the maxactivity is -infty */
2532  else if( neginf > 0 )
2533  {
2534  *maxactivity = -SCIPinfinity(scip);
2535  *issettoinfinity = TRUE;
2536  *istight = TRUE;
2537  }
2538  /* if we have pos. huge contributions or do not need a good relaxation, we just return +infty as maxactivity */
2539  else if( poshuge > 0 || ( neghuge > 0 && !goodrelax ) )
2540  {
2541  *maxactivity = SCIPinfinity(scip);
2542  *issettoinfinity = TRUE;
2543  *istight = FALSE;
2544  }
2545  else
2546  {
2547  SCIP_Real QUAD(tmpactivity);
2548 
2549  /* recompute maxactivity if it is not valid */
2550  if( global )
2551  {
2552  if( !consdata->validglbmaxact )
2553  consdataRecomputeGlbMaxactivity(scip, consdata);
2554  assert(consdata->validglbmaxact);
2555 
2556  QUAD_ASSIGN_Q(tmpactivity, consdata->glbmaxactivity);
2557  }
2558  else
2559  {
2560  if( !consdata->validmaxact )
2561  consdataRecomputeMaxactivity(scip, consdata);
2562  assert(consdata->validmaxact);
2563 
2564  QUAD_ASSIGN_Q(tmpactivity, consdata->maxactivity);
2565  }
2566 
2567  /* calculate residual maxactivity */
2568  SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
2569 
2570  /* we have no infinite and no pos. huge contributions, but neg. huge contributions; a feasible relaxation of the
2571  * maxactivity is given by subtracting the number of negative huge contributions times the huge value
2572  */
2573  if( neghuge > 0 )
2574  {
2575  SCIPquadprecSumQD(tmpactivity, tmpactivity, -neghuge * SCIPgetHugeValue(scip));
2576  *istight = FALSE;
2577  }
2578  /* all counters are zero, so the maxactivity is tight */
2579  else
2580  *istight = TRUE;
2581 
2582  /* round residual maxactivity */
2583  *maxactivity = QUAD_TO_DBL(tmpactivity);
2584  *issettoinfinity = FALSE;
2585  }
2586 }
2587 
2588 /** gets activity bounds for constraint */
2589 static
2591  SCIP* scip, /**< SCIP data structure */
2592  SCIP_CONSDATA* consdata, /**< linear constraint */
2593  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2594  * relaxed activities ignored, anyway? */
2595  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2596  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2597  SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
2598  * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2599  SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
2600  * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2601  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2602  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2603 
2604  )
2605 {
2606  assert(scip != NULL);
2607  assert(consdata != NULL);
2608  assert(minactivity != NULL);
2609  assert(maxactivity != NULL);
2610  assert(isminsettoinfinity != NULL);
2611  assert(ismaxsettoinfinity != NULL);
2612 
2613  if( !consdata->validactivities )
2614  {
2615  consdataCalcActivities(scip, consdata);
2616  assert(consdata->validminact);
2617  assert(consdata->validmaxact);
2618  }
2619  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2620  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2621  assert(consdata->minactivityneginf >= 0);
2622  assert(consdata->minactivityposinf >= 0);
2623  assert(consdata->maxactivityneginf >= 0);
2624  assert(consdata->maxactivityposinf >= 0);
2625 
2626  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2627  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2628  minactivity, ismintight, isminsettoinfinity);
2629 
2630  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2631  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2632  maxactivity, ismaxtight, ismaxsettoinfinity);
2633 }
2634 
2635 /** calculates activity bounds for constraint after setting variable to zero */
2636 static
2638  SCIP* scip, /**< SCIP data structure */
2639  SCIP_CONSDATA* consdata, /**< linear constraint */
2640  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2641  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2642  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2643  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2644  )
2645 {
2646  SCIP_VAR* var;
2647  SCIP_Real val;
2648  SCIP_Real lb;
2649  SCIP_Real ub;
2650  int v;
2651 
2652  assert(scip != NULL);
2653  assert(consdata != NULL);
2654  assert(cancelvar != NULL);
2655  assert(resactivity != NULL);
2657  *resactivity = 0.0;
2658 
2659  for( v = 0; v < consdata->nvars; ++v )
2660  {
2661  var = consdata->vars[v];
2662  assert(var != NULL);
2663  if( var == cancelvar )
2664  continue;
2665 
2666  val = consdata->vals[v];
2667 
2668  if( useglobalbounds )
2669  {
2670  lb = SCIPvarGetLbGlobal(var);
2671  ub = SCIPvarGetUbGlobal(var);
2672  }
2673  else
2674  {
2675  lb = SCIPvarGetLbLocal(var);
2676  ub = SCIPvarGetUbLocal(var);
2677  }
2678 
2679  assert(!SCIPisZero(scip, val));
2680  assert(SCIPisLE(scip, lb, ub));
2681 
2682  if( val > 0.0 )
2683  {
2684  if( isminresact )
2685  {
2686  assert(!SCIPisInfinity(scip, -lb));
2687  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2688  *resactivity += val*lb;
2689  }
2690  else
2691  {
2692  assert(!SCIPisInfinity(scip, ub));
2693  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2694  *resactivity += val*ub;
2695  }
2696  }
2697  else
2698  {
2699  if( isminresact)
2700  {
2701  assert(!SCIPisInfinity(scip, ub));
2702  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2703  *resactivity += val*ub;
2704  }
2705  else
2706  {
2707  assert(!SCIPisInfinity(scip, -lb));
2708  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2709  *resactivity += val*lb;
2710  }
2711  }
2712  }
2713  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2714 }
2715 
2716 /** gets activity bounds for constraint after setting variable to zero */
2717 static
2719  SCIP* scip, /**< SCIP data structure */
2720  SCIP_CONSDATA* consdata, /**< linear constraint */
2721  SCIP_VAR* var, /**< variable to calculate activity residual for */
2722  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2723  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2724  * relaxed acticities ignored, anyway? */
2725  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2726  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2727  SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
2728  * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
2729  SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
2730  * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
2731  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2732  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2733  )
2734 {
2735  SCIP_Real minactbound;
2736  SCIP_Real maxactbound;
2737  SCIP_Real absval;
2738 
2739  assert(scip != NULL);
2740  assert(consdata != NULL);
2741  assert(var != NULL);
2742  assert(minresactivity != NULL);
2743  assert(maxresactivity != NULL);
2744  assert(ismintight != NULL);
2745  assert(ismaxtight != NULL);
2746  assert(isminsettoinfinity != NULL);
2747  assert(ismaxsettoinfinity != NULL);
2748 
2749  /* get activity bounds of linear constraint */
2750  if( !consdata->validactivities )
2751  {
2752  consdataCalcActivities(scip, consdata);
2753  assert(consdata->validminact);
2754  assert(consdata->validmaxact);
2755  }
2756  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2757  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2758  assert(consdata->minactivityneginf >= 0);
2759  assert(consdata->minactivityposinf >= 0);
2760  assert(consdata->maxactivityneginf >= 0);
2761  assert(consdata->maxactivityposinf >= 0);
2762  assert(consdata->minactivityneghuge >= 0);
2763  assert(consdata->minactivityposhuge >= 0);
2764  assert(consdata->maxactivityneghuge >= 0);
2765  assert(consdata->maxactivityposhuge >= 0);
2766 
2767  if( val > 0.0 )
2768  {
2769  minactbound = SCIPvarGetLbLocal(var);
2770  maxactbound = SCIPvarGetUbLocal(var);
2771  absval = val;
2772  }
2773  else
2774  {
2775  minactbound = -SCIPvarGetUbLocal(var);
2776  maxactbound = -SCIPvarGetLbLocal(var);
2777  absval = -val;
2778  }
2779 
2780  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2781  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2782  */
2783  if( SCIPisInfinity(scip, minactbound) )
2784  {
2785  assert(consdata->minactivityposinf >= 1);
2786 
2787  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2788  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2789  minresactivity, ismintight, isminsettoinfinity);
2790  }
2791  else if( SCIPisInfinity(scip, -minactbound) )
2792  {
2793  assert(consdata->minactivityneginf >= 1);
2794 
2795  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2796  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2797  minresactivity, ismintight, isminsettoinfinity);
2798  }
2799  else if( SCIPisHugeValue(scip, minactbound * absval) )
2800  {
2801  assert(consdata->minactivityposhuge >= 1);
2802 
2803  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2804  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2805  minresactivity, ismintight, isminsettoinfinity);
2806  }
2807  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2808  {
2809  assert(consdata->minactivityneghuge >= 1);
2810 
2811  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2812  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2813  minresactivity, ismintight, isminsettoinfinity);
2814  }
2815  else
2816  {
2817  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2818  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2819  minresactivity, ismintight, isminsettoinfinity);
2820  }
2821 
2822  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2823  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2824  */
2825  if( SCIPisInfinity(scip, -maxactbound) )
2826  {
2827  assert(consdata->maxactivityneginf >= 1);
2828 
2829  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2830  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2831  maxresactivity, ismaxtight, ismaxsettoinfinity);
2832  }
2833  else if( SCIPisInfinity(scip, maxactbound) )
2834  {
2835  assert(consdata->maxactivityposinf >= 1);
2836 
2837  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2838  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2839  maxresactivity, ismaxtight, ismaxsettoinfinity);
2840  }
2841  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2842  {
2843  assert(consdata->maxactivityposhuge >= 1);
2844 
2845  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2846  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2847  maxresactivity, ismaxtight, ismaxsettoinfinity);
2848  }
2849  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2850  {
2851  assert(consdata->maxactivityneghuge >= 1);
2852 
2853  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2854  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2855  maxresactivity, ismaxtight, ismaxsettoinfinity);
2856  }
2857  else
2858  {
2859  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2860  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2861  maxresactivity, ismaxtight, ismaxsettoinfinity);
2862  }
2863 }
2864 
2865 /** gets global activity bounds for constraint */
2866 static
2868  SCIP* scip, /**< SCIP data structure */
2869  SCIP_CONSDATA* consdata, /**< linear constraint */
2870  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2871  * relaxed acticities ignored, anyway? */
2872  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2873  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2874  SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
2875  * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2876  SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
2877  * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2878  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2879  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2880  )
2881 {
2882  assert(scip != NULL);
2883  assert(consdata != NULL);
2884  assert((glbminactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL)
2885  || (glbmaxactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
2887  if( !consdata->validactivities )
2888  {
2889  consdataCalcActivities(scip, consdata);
2890  assert(consdata->validglbminact);
2891  assert(consdata->validglbmaxact);
2892  }
2893  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2894  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2895  assert(consdata->glbminactivityneginf >= 0);
2896  assert(consdata->glbminactivityposinf >= 0);
2897  assert(consdata->glbmaxactivityneginf >= 0);
2898  assert(consdata->glbmaxactivityposinf >= 0);
2899  assert(consdata->glbminactivityneghuge >= 0);
2900  assert(consdata->glbminactivityposhuge >= 0);
2901  assert(consdata->glbmaxactivityneghuge >= 0);
2902  assert(consdata->glbmaxactivityposhuge >= 0);
2903 
2904  if( glbminactivity != NULL )
2905  {
2906  assert(isminsettoinfinity != NULL);
2907  assert(ismintight != NULL);
2908 
2909  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2910  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2911  glbminactivity, ismintight, isminsettoinfinity);
2912  }
2913 
2914  if( glbmaxactivity != NULL )
2915  {
2916  assert(ismaxsettoinfinity != NULL);
2917  assert(ismaxtight != NULL);
2918 
2919  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2920  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2921  glbmaxactivity, ismaxtight, ismaxsettoinfinity);
2922  }
2923 }
2924 
2925 /** gets global activity bounds for constraint after setting variable to zero */
2926 static
2928  SCIP* scip, /**< SCIP data structure */
2929  SCIP_CONSDATA* consdata, /**< linear constraint */
2930  SCIP_VAR* var, /**< variable to calculate activity residual for */
2931  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2932  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2933  * relaxed acticities ignored, anyway? */
2934  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2935  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2936  SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
2937  * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
2938  SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
2939  * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
2940  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2941  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2942  )
2943 {
2944  SCIP_Real minactbound;
2945  SCIP_Real maxactbound;
2946  SCIP_Real absval;
2947 
2948  assert(scip != NULL);
2949  assert(consdata != NULL);
2950  assert(var != NULL);
2951  assert((minresactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL )
2952  || (maxresactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
2953 
2954  /* get activity bounds of linear constraint */
2955  if( !consdata->validactivities )
2956  consdataCalcActivities(scip, consdata);
2957 
2958  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2959  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2960  assert(consdata->glbminactivityneginf >= 0);
2961  assert(consdata->glbminactivityposinf >= 0);
2962  assert(consdata->glbmaxactivityneginf >= 0);
2963  assert(consdata->glbmaxactivityposinf >= 0);
2964 
2965  if( val > 0.0 )
2966  {
2967  minactbound = SCIPvarGetLbGlobal(var);
2968  maxactbound = SCIPvarGetUbGlobal(var);
2969  absval = val;
2970  }
2971  else
2972  {
2973  minactbound = -SCIPvarGetUbGlobal(var);
2974  maxactbound = -SCIPvarGetLbGlobal(var);
2975  absval = -val;
2976  }
2977 
2978  if( minresactivity != NULL )
2979  {
2980  assert(isminsettoinfinity != NULL);
2981  assert(ismintight != NULL);
2982 
2983  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2984  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2985  */
2986  if( SCIPisInfinity(scip, minactbound) )
2987  {
2988  assert(consdata->glbminactivityposinf >= 1);
2989 
2990  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2991  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2992  minresactivity, ismintight, isminsettoinfinity);
2993  }
2994  else if( SCIPisInfinity(scip, -minactbound) )
2995  {
2996  assert(consdata->glbminactivityneginf >= 1);
2997 
2998  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2999  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3000  minresactivity, ismintight, isminsettoinfinity);
3001  }
3002  else if( SCIPisHugeValue(scip, minactbound * absval) )
3003  {
3004  assert(consdata->glbminactivityposhuge >= 1);
3005 
3006  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3007  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3008  minresactivity, ismintight, isminsettoinfinity);
3009  }
3010  else if( SCIPisHugeValue(scip, -minactbound * absval) )
3011  {
3012  assert(consdata->glbminactivityneghuge >= 1);
3013 
3014  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3015  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
3016  minresactivity, ismintight, isminsettoinfinity);
3017  }
3018  else
3019  {
3020  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3021  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
3022  goodrelax, minresactivity, ismintight, isminsettoinfinity);
3023  }
3024  }
3025 
3026  if( maxresactivity != NULL )
3027  {
3028  assert(ismaxsettoinfinity != NULL);
3029  assert(ismaxtight != NULL);
3030 
3031  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
3032  * and contribution of variable set to zero that has to be subtracted from finite part of activity
3033  */
3034  if( SCIPisInfinity(scip, -maxactbound) )
3035  {
3036  assert(consdata->glbmaxactivityneginf >= 1);
3037 
3038  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
3039  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3040  maxresactivity, ismaxtight, ismaxsettoinfinity);
3041  }
3042  else if( SCIPisInfinity(scip, maxactbound) )
3043  {
3044  assert(consdata->glbmaxactivityposinf >= 1);
3045 
3046  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
3047  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3048  maxresactivity, ismaxtight, ismaxsettoinfinity);
3049  }
3050  else if( SCIPisHugeValue(scip, absval * maxactbound) )
3051  {
3052  assert(consdata->glbmaxactivityposhuge >= 1);
3053 
3054  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3055  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3056  maxresactivity, ismaxtight, ismaxsettoinfinity);
3057  }
3058  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3059  {
3060  assert(consdata->glbmaxactivityneghuge >= 1);
3061 
3062  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3063  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3064  maxresactivity, ismaxtight, ismaxsettoinfinity);
3065  }
3066  else
3067  {
3068  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3069  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3070  goodrelax, maxresactivity, ismaxtight, ismaxsettoinfinity);
3071  }
3072  }
3073 }
3074 
3075 /** calculates the activity of the linear constraint for given solution */
3076 static
3078  SCIP* scip, /**< SCIP data structure */
3079  SCIP_CONSDATA* consdata, /**< linear constraint data */
3080  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3081  )
3082 {
3083  SCIP_Real activity;
3084 
3085  assert(scip != NULL);
3086  assert(consdata != NULL);
3087 
3088  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3089  activity = consdataComputePseudoActivity(scip, consdata);
3090  else
3091  {
3092  SCIP_Real solval;
3093  int nposinf;
3094  int nneginf;
3095  SCIP_Bool negsign;
3096  int v;
3097 
3098  activity = 0.0;
3099  nposinf = 0;
3100  nneginf = 0;
3101 
3102  for( v = 0; v < consdata->nvars; ++v )
3103  {
3104  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3105 
3106  if( consdata->vals[v] < 0 )
3107  negsign = TRUE;
3108  else
3109  negsign = FALSE;
3110 
3111  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3112  ++nposinf;
3113  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3114  ++nneginf;
3115  else
3116  activity += consdata->vals[v] * solval;
3117  }
3118  assert(nneginf >= 0 && nposinf >= 0);
3119 
3120  SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3121 
3122  /* check for amount of infinity values and correct the activity */
3123  if( nposinf > 0 && nneginf > 0 )
3124  activity = (consdata->rhs + consdata->lhs) / 2;
3125  else if( nposinf > 0 )
3126  activity = SCIPinfinity(scip);
3127  else if( nneginf > 0 )
3128  activity = -SCIPinfinity(scip);
3129 
3130  SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3131  }
3132 
3133  if( activity == SCIP_INVALID ) /*lint !e777*/
3134  return activity;
3135  else if( activity < 0 )
3136  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3137  else
3138  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3139 
3140  return activity;
3141 }
3142 
3143 /** calculates the feasibility of the linear constraint for given solution */
3144 static
3146  SCIP* scip, /**< SCIP data structure */
3147  SCIP_CONSDATA* consdata, /**< linear constraint data */
3148  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3149  )
3150 {
3151  SCIP_Real activity;
3152 
3153  assert(scip != NULL);
3154  assert(consdata != NULL);
3155 
3156  activity = consdataGetActivity(scip, consdata, sol);
3157 
3158  if( activity == SCIP_INVALID ) /*lint !e777*/
3159  return -SCIPinfinity(scip);
3160 
3161  return MIN(consdata->rhs - activity, activity - consdata->lhs);
3162 }
3163 
3164 /** updates bit signatures after adding a single coefficient */
3165 static
3167  SCIP_CONSDATA* consdata, /**< linear constraint data */
3168  int pos /**< position of coefficient to update signatures for */
3169  )
3170 {
3171  uint64_t varsignature;
3172  SCIP_Real lb;
3173  SCIP_Real ub;
3174  SCIP_Real val;
3175 
3176  assert(consdata != NULL);
3177  assert(consdata->validsignature);
3178 
3179  varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3180  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3181  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3182  val = consdata->vals[pos];
3183  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3184  consdata->possignature |= varsignature;
3185  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3186  consdata->negsignature |= varsignature;
3187 }
3188 
3189 /** calculates the bit signatures of the given constraint data */
3190 static
3192  SCIP_CONSDATA* consdata /**< linear constraint data */
3193  )
3194 {
3195  assert(consdata != NULL);
3196 
3197  if( !consdata->validsignature )
3198  {
3199  int i;
3200 
3201  consdata->validsignature = TRUE;
3202  consdata->possignature = 0;
3203  consdata->negsignature = 0;
3204  for( i = 0; i < consdata->nvars; ++i )
3205  consdataUpdateSignatures(consdata, i);
3206  }
3207 }
3208 
3209 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3210 static
3211 SCIP_DECL_SORTINDCOMP(consdataCompVar)
3212 { /*lint --e{715}*/
3213  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3214  SCIP_VAR* var1;
3215  SCIP_VAR* var2;
3216 
3217  assert(consdata != NULL);
3218  assert(0 <= ind1 && ind1 < consdata->nvars);
3219  assert(0 <= ind2 && ind2 < consdata->nvars);
3220 
3221  var1 = consdata->vars[ind1];
3222  var2 = consdata->vars[ind2];
3223 
3224  /* exactly one variable is binary */
3225  if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3226  {
3227  return (SCIPvarIsBinary(var1) ? -1 : +1);
3228  }
3229  /* both variables are binary */
3230  else if( SCIPvarIsBinary(var1) )
3231  {
3232  return SCIPvarCompare(var1, var2);
3233  }
3234  else
3235  {
3236  SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3237  SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3238 
3239  if( vartype1 < vartype2 )
3240  return -1;
3241  else if( vartype1 > vartype2 )
3242  return +1;
3243  else
3244  return SCIPvarCompare(var1, var2);
3245  }
3246 }
3247 
3248 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3249 static
3250 SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
3251 { /*lint --e{715}*/
3252  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3253  SCIP_VAR* var1;
3254  SCIP_VAR* var2;
3255 
3256  assert(consdata != NULL);
3257  assert(0 <= ind1 && ind1 < consdata->nvars);
3258  assert(0 <= ind2 && ind2 < consdata->nvars);
3259 
3260  var1 = consdata->vars[ind1];
3261  var2 = consdata->vars[ind2];
3262 
3263  /* exactly one variable is binary */
3264  if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3265  {
3266  return (SCIPvarIsBinary(var1) ? -1 : +1);
3267  }
3268  /* both variables are binary */
3269  else if( SCIPvarIsBinary(var1) )
3270  {
3271  SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3272  SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3273 
3274  if( EPSGT(abscoef1, abscoef2, 1e-9) )
3275  return -1;
3276  else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3277  return +1;
3278  else
3279  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3280  }
3281  else
3282  {
3283  SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3284  SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3285 
3286  if( vartype1 < vartype2 )
3287  {
3288  return -1;
3289  }
3290  else if( vartype1 > vartype2 )
3291  {
3292  return +1;
3293  }
3294  else
3295  {
3296  /* both variables are continuous */
3297  if( !SCIPvarIsIntegral(var1) )
3298  {
3299  assert(!SCIPvarIsIntegral(var2));
3300  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3301  }
3302  else
3303  {
3304  SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3305  SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3306 
3307  if( EPSGT(abscont1, abscont2, 1e-9) )
3308  return -1;
3309  else if( EPSGT(abscont2, abscont1, 1e-9) )
3310  return +1;
3311  else
3312  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3313  }
3314  }
3315  }
3316 }
3317 
3318 /** permutes the constraint's variables according to a given permutation. */
3319 static
3320 void permSortConsdata(
3321  SCIP_CONSDATA* consdata, /**< the constraint data */
3322  int* perm, /**< the target permutation */
3323  int nvars /**< the number of variables */
3324  )
3325 { /*lint --e{715}*/
3326  SCIP_VAR* varv;
3327  SCIP_EVENTDATA* eventdatav;
3328  SCIP_Real valv;
3329  int v;
3330  int i;
3331  int nexti;
3332 
3333  assert(perm != NULL);
3334  assert(consdata != NULL);
3335 
3336  /* permute the variables in the linear constraint according to the target permutation */
3337  eventdatav = NULL;
3338  for( v = 0; v < nvars; ++v )
3339  {
3340  if( perm[v] != v )
3341  {
3342  varv = consdata->vars[v];
3343  valv = consdata->vals[v];
3344  if( consdata->eventdata != NULL )
3345  eventdatav = consdata->eventdata[v];
3346  i = v;
3347  do
3348  {
3349  assert(0 <= perm[i] && perm[i] < nvars);
3350  assert(perm[i] != i);
3351  consdata->vars[i] = consdata->vars[perm[i]];
3352  consdata->vals[i] = consdata->vals[perm[i]];
3353  if( consdata->eventdata != NULL )
3354  {
3355  consdata->eventdata[i] = consdata->eventdata[perm[i]];
3356  consdata->eventdata[i]->varpos = i;
3357  }
3358  nexti = perm[i];
3359  perm[i] = i;
3360  i = nexti;
3361  }
3362  while( perm[i] != v );
3363  consdata->vars[i] = varv;
3364  consdata->vals[i] = valv;
3365  if( consdata->eventdata != NULL )
3366  {
3367  consdata->eventdata[i] = eventdatav;
3368  consdata->eventdata[i]->varpos = i;
3369  }
3370  perm[i] = i;
3371  }
3372  }
3373 #ifdef SCIP_DEBUG
3374  /* check sorting */
3375  for( v = 0; v < nvars; ++v )
3376  {
3377  assert(perm[v] == v);
3378  assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3379  }
3380 #endif
3381 }
3382 
3383 /** sorts linear constraint's variables depending on the stage of the solving process:
3384  * - during PRESOLVING
3385  * sorts variables by binaries, integers, implicit integers, and continuous variables,
3386  * and the variables of the same type by non-decreasing variable index
3387  *
3388  * - during SOLVING
3389  * sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables,
3390  * and binary and integer variables by their global max activity delta (within each group),
3391  * ties within a group are broken by problem index of the variable.
3392  *
3393  * This fastens the propagation time of the constraint handler.
3394  */
3395 static
3397  SCIP* scip, /**< SCIP data structure */
3398  SCIP_CONSDATA* consdata /**< linear constraint data */
3399  )
3400 {
3401  assert(scip != NULL);
3402  assert(consdata != NULL);
3403 
3404  /* check if there are variables for sorting */
3405  if( consdata->nvars <= 1 )
3406  {
3407  consdata->indexsorted = TRUE;
3408  consdata->coefsorted = TRUE;
3409  consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3410  }
3411  else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3412  || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3413  {
3414  int* perm;
3415  int v;
3416 
3417  /* get temporary memory to store the sorted permutation */
3418  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3419 
3420  /* call sorting method */
3421  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
3422  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3423  else
3424  SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3425 
3426  permSortConsdata(consdata, perm, consdata->nvars);
3427 
3428  /* free temporary memory */
3429  SCIPfreeBufferArray(scip, &perm);
3430 
3431  if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE )
3432  {
3433  consdata->indexsorted = FALSE;
3434  consdata->coefsorted = TRUE;
3435 
3436  /* count binary variables in the sorted vars array */
3437  consdata->nbinvars = 0;
3438  for( v = 0; v < consdata->nvars; ++v )
3439  {
3440  if( SCIPvarIsBinary(consdata->vars[v]) )
3441  ++consdata->nbinvars;
3442  else
3443  break;
3444  }
3445  }
3446  else
3447  {
3448  consdata->indexsorted = TRUE;
3449  consdata->coefsorted = FALSE;
3450  }
3451  }
3452 
3453  return SCIP_OKAY;
3454 }
3455 
3456 
3457 /*
3458  * local linear constraint handler methods
3459  */
3460 
3461 /** sets left hand side of linear constraint */
3462 static
3464  SCIP* scip, /**< SCIP data structure */
3465  SCIP_CONS* cons, /**< linear constraint */
3466  SCIP_Real lhs /**< new left hand side */
3467  )
3468 {
3469  SCIP_CONSDATA* consdata;
3470  SCIP_Bool locked;
3471  int i;
3472 
3473  assert(scip != NULL);
3474  assert(cons != NULL);
3475 
3476  /* adjust value to be not beyond infinity */
3477  if( SCIPisInfinity(scip, -lhs) )
3478  lhs = -SCIPinfinity(scip);
3479  else if( SCIPisInfinity(scip, lhs) )
3480  lhs = SCIPinfinity(scip);
3481 
3482  consdata = SCIPconsGetData(cons);
3483  assert(consdata != NULL);
3484  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3485 
3486  /* check whether the side is not changed */
3487  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3488  return SCIP_OKAY;
3489 
3490  assert(!SCIPisInfinity(scip, ABS(consdata->lhs)) || !SCIPisInfinity(scip, ABS(lhs)));
3491 
3492  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3493  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3494  {
3495  consdata->rhs = lhs;
3496  assert(consdata->row == NULL);
3497  }
3498 
3499  locked = FALSE;
3500  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3501  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3502 
3503  /* if necessary, update the rounding locks of variables */
3504  if( locked )
3505  {
3506  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3507  {
3508  SCIP_VAR** vars;
3509  SCIP_Real* vals;
3510  int v;
3511 
3512  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3513  vars = consdata->vars;
3514  vals = consdata->vals;
3515 
3516  for( v = 0; v < consdata->nvars; ++v )
3517  {
3518  assert(vars[v] != NULL);
3519  assert(!SCIPisZero(scip, vals[v]));
3520 
3521  if( SCIPisPositive(scip, vals[v]) )
3522  {
3523  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3524  }
3525  else
3526  {
3527  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3528  }
3529  }
3530  }
3531  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3532  {
3533  SCIP_VAR** vars;
3534  SCIP_Real* vals;
3535  int v;
3536 
3537  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3538  vars = consdata->vars;
3539  vals = consdata->vals;
3540 
3541  for( v = 0; v < consdata->nvars; ++v )
3542  {
3543  assert(vars[v] != NULL);
3544  assert(!SCIPisZero(scip, vals[v]));
3545 
3546  if( SCIPisPositive(scip, vals[v]) )
3547  {
3548  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3549  }
3550  else
3551  {
3552  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3553  }
3554  }
3555  }
3556  }
3557 
3558  /* 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 */
3559  if( !SCIPisInfinity(scip, ABS(lhs)) && SCIPisGT(scip, lhs, consdata->lhs) )
3560  {
3561  consdata->boundstightened = 0;
3562  consdata->presolved = FALSE;
3563  consdata->cliquesadded = FALSE;
3564  consdata->implsadded = FALSE;
3565 
3566  /* mark the constraint for propagation */
3567  if( SCIPconsIsTransformed(cons) )
3568  {
3569  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3570  }
3571  }
3572 
3573  /* set new left hand side and update constraint data */
3574  consdata->lhs = lhs;
3575  consdata->changed = TRUE;
3576  consdata->normalized = FALSE;
3577  consdata->upgradetried = FALSE;
3578  consdata->rangedrowpropagated = 0;
3579 
3580  /* update the lhs of the LP row */
3581  if( consdata->row != NULL )
3582  {
3583  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3584  }
3585 
3586  return SCIP_OKAY;
3587 }
3588 
3589 /** sets right hand side of linear constraint */
3590 static
3592  SCIP* scip, /**< SCIP data structure */
3593  SCIP_CONS* cons, /**< linear constraint */
3594  SCIP_Real rhs /**< new right hand side */
3595  )
3596 {
3597  SCIP_CONSDATA* consdata;
3598  SCIP_Bool locked;
3599  int i;
3600 
3601  assert(scip != NULL);
3602  assert(cons != NULL);
3603 
3604  /* adjust value to be not beyond infinity */
3605  if( SCIPisInfinity(scip, rhs) )
3606  rhs = SCIPinfinity(scip);
3607  else if( SCIPisInfinity(scip, -rhs) )
3608  rhs = -SCIPinfinity(scip);
3609 
3610  consdata = SCIPconsGetData(cons);
3611  assert(consdata != NULL);
3612  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3613 
3614  /* check whether the side is not changed */
3615  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3616  return SCIP_OKAY;
3617 
3618  assert(!SCIPisInfinity(scip, ABS(consdata->rhs)) || !SCIPisInfinity(scip, ABS(rhs)));
3619 
3620  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3621  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3622  {
3623  consdata->lhs = rhs;
3624  assert(consdata->row == NULL);
3625  }
3626 
3627  locked = FALSE;
3628  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3629  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3630 
3631  /* if necessary, update the rounding locks of variables */
3632  if( locked )
3633  {
3634  assert(SCIPconsIsTransformed(cons));
3635 
3636  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3637  {
3638  SCIP_VAR** vars;
3639  SCIP_Real* vals;
3640  int v;
3641 
3642  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3643  vars = consdata->vars;
3644  vals = consdata->vals;
3645 
3646  for( v = 0; v < consdata->nvars; ++v )
3647  {
3648  assert(vars[v] != NULL);
3649  assert(!SCIPisZero(scip, vals[v]));
3650 
3651  if( SCIPisPositive(scip, vals[v]) )
3652  {
3653  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3654  }
3655  else
3656  {
3657  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3658  }
3659  }
3660  }
3661  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3662  {
3663  SCIP_VAR** vars;
3664  SCIP_Real* vals;
3665  int v;
3666 
3667  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3668  vars = consdata->vars;
3669  vals = consdata->vals;
3670 
3671  for( v = 0; v < consdata->nvars; ++v )
3672  {
3673  assert(vars[v] != NULL);
3674  assert(!SCIPisZero(scip, vals[v]));
3675 
3676  if( SCIPisPositive(scip, vals[v]) )
3677  {
3678  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3679  }
3680  else
3681  {
3682  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3683  }
3684  }
3685  }
3686  }
3687 
3688  /* 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 */
3689  if( !SCIPisInfinity(scip, ABS(rhs)) && SCIPisLT(scip, rhs, consdata->rhs) )
3690  {
3691  consdata->boundstightened = 0;
3692  consdata->presolved = FALSE;
3693  consdata->cliquesadded = FALSE;
3694  consdata->implsadded = FALSE;
3695 
3696  /* mark the constraint for propagation */
3697  if( SCIPconsIsTransformed(cons) )
3698  {
3699  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3700  }
3701  }
3702 
3703  /* set new right hand side and update constraint data */
3704  consdata->rhs = rhs;
3705  consdata->changed = TRUE;
3706  consdata->normalized = FALSE;
3707  consdata->upgradetried = FALSE;
3708  consdata->rangedrowpropagated = 0;
3709 
3710  /* update the rhs of the LP row */
3711  if( consdata->row != NULL )
3712  {
3713  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3714  }
3715 
3716  return SCIP_OKAY;
3717 }
3718 
3719 /** adds coefficient in linear constraint */
3720 static
3722  SCIP* scip, /**< SCIP data structure */
3723  SCIP_CONS* cons, /**< linear constraint */
3724  SCIP_VAR* var, /**< variable of constraint entry */
3725  SCIP_Real val /**< coefficient of constraint entry */
3726  )
3727 {
3728  SCIP_CONSDATA* consdata;
3729  SCIP_Bool transformed;
3730 
3731  assert(scip != NULL);
3732  assert(cons != NULL);
3733  assert(var != NULL);
3734 
3735  /* relaxation-only variables must not be used in checked or enforced constraints */
3736  assert(!SCIPvarIsRelaxationOnly(var) || (!SCIPconsIsChecked(cons) && !SCIPconsIsEnforced(cons)));
3737 
3738  /* ignore coefficient if it is nearly zero */
3739  if( SCIPisZero(scip, val) )
3740  return SCIP_OKAY;
3741 
3742  consdata = SCIPconsGetData(cons);
3743  assert(consdata != NULL);
3744 
3745  /* are we in the transformed problem? */
3746  transformed = SCIPconsIsTransformed(cons);
3747 
3748  /* always use transformed variables in transformed constraints */
3749  if( transformed )
3750  {
3751  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3752  }
3753  assert(var != NULL);
3754  assert(transformed == SCIPvarIsTransformed(var));
3755 
3756  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3757  consdata->vars[consdata->nvars] = var;
3758  consdata->vals[consdata->nvars] = val;
3759  consdata->nvars++;
3760 
3761  /* capture variable */
3762  SCIP_CALL( SCIPcaptureVar(scip, var) );
3763 
3764  /* if we are in transformed problem, the variable needs an additional event data */
3765  if( transformed )
3766  {
3767  if( consdata->eventdata != NULL )
3768  {
3769  SCIP_CONSHDLR* conshdlr;
3770  SCIP_CONSHDLRDATA* conshdlrdata;
3771 
3772  /* check for event handler */
3773  conshdlr = SCIPconsGetHdlr(cons);
3774  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3775  assert(conshdlrdata != NULL);
3776  assert(conshdlrdata->eventhdlr != NULL);
3777 
3778  /* initialize eventdata array */
3779  consdata->eventdata[consdata->nvars-1] = NULL;
3780 
3781  /* catch bound change events of variable */
3782  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3783  }
3784 
3785  /* update minimum and maximum activities */
3786  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3787 
3788  /* update maximum activity delta */
3789  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3790  {
3791  SCIP_Real lb;
3792  SCIP_Real ub;
3793 
3794  lb = SCIPvarGetLbLocal(var);
3795  ub = SCIPvarGetUbLocal(var);
3796 
3797  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3798  {
3799  consdata->maxactdelta = SCIPinfinity(scip);
3800  consdata->maxactdeltavar = var;
3801  }
3802  else
3803  {
3804  SCIP_Real domain = ub - lb;
3805  SCIP_Real delta = REALABS(val) * domain;
3806 
3807  if( delta > consdata->maxactdelta )
3808  {
3809  consdata->maxactdelta = delta;
3810  consdata->maxactdeltavar = var;
3811  }
3812  }
3813  }
3814  }
3815 
3816  /* install rounding locks for new variable */
3817  SCIP_CALL( lockRounding(scip, cons, var, val) );
3818 
3819  /* mark the constraint for propagation */
3820  if( transformed )
3821  {
3822  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3823  }
3824 
3825  consdata->boundstightened = 0;
3826  consdata->presolved = FALSE;
3827  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3828 
3829  if( consdata->validsignature )
3830  consdataUpdateSignatures(consdata, consdata->nvars-1);
3831 
3832  consdata->changed = TRUE;
3833  consdata->normalized = FALSE;
3834  consdata->upgradetried = FALSE;
3835  consdata->cliquesadded = FALSE;
3836  consdata->implsadded = FALSE;
3837  consdata->rangedrowpropagated = 0;
3838 
3839  if( consdata->nvars == 1 )
3840  {
3841  consdata->indexsorted = TRUE;
3842  consdata->coefsorted = TRUE;
3843  consdata->merged = TRUE;
3844  }
3845  else
3846  {
3847  consdata->merged = FALSE;
3848 
3849  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
3850  {
3851  consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3852  consdata->coefsorted = FALSE;
3853  }
3854  else
3855  {
3856  consdata->indexsorted = FALSE;
3857  consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3858  }
3859  }
3860 
3861  /* update hascontvar and hasnonbinvar flags */
3862  if( consdata->hasnonbinvalid && !consdata->hascontvar )
3863  {
3864  SCIP_VARTYPE vartype = SCIPvarGetType(var);
3865 
3866  if( vartype != SCIP_VARTYPE_BINARY )
3867  {
3868  consdata->hasnonbinvar = TRUE;
3869 
3870  if( vartype == SCIP_VARTYPE_CONTINUOUS )
3871  consdata->hascontvar = TRUE;
3872  }
3873  }
3874 
3875  /* add the new coefficient to the LP row */
3876  if( consdata->row != NULL )
3877  {
3878  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3879  }
3880 
3881  return SCIP_OKAY;
3882 }
3883 
3884 /** deletes coefficient at given position from linear constraint data */
3885 static
3887  SCIP* scip, /**< SCIP data structure */
3888  SCIP_CONS* cons, /**< linear constraint */
3889  int pos /**< position of coefficient to delete */
3890  )
3891 {
3892  SCIP_CONSDATA* consdata;
3893  SCIP_VAR* var;
3894  SCIP_Real val;
3895 
3896  assert(scip != NULL);
3897  assert(cons != NULL);
3898 
3899  consdata = SCIPconsGetData(cons);
3900  assert(consdata != NULL);
3901  assert(0 <= pos && pos < consdata->nvars);
3902 
3903  var = consdata->vars[pos];
3904  val = consdata->vals[pos];
3905  assert(var != NULL);
3906 
3907  /* remove rounding locks for deleted variable */
3908  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3909 
3910  /* if we are in transformed problem, delete the event data of the variable */
3911  if( SCIPconsIsTransformed(cons) )
3912  {
3913  SCIP_CONSHDLR* conshdlr;
3914  SCIP_CONSHDLRDATA* conshdlrdata;
3915 
3916  /* check for event handler */
3917  conshdlr = SCIPconsGetHdlr(cons);
3918  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3919  assert(conshdlrdata != NULL);
3920  assert(conshdlrdata->eventhdlr != NULL);
3921 
3922  /* drop bound change events of variable */
3923  if( consdata->eventdata != NULL )
3924  {
3925  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3926  assert(consdata->eventdata[pos] == NULL);
3927  }
3928  }
3929 
3930  /* move the last variable to the free slot */
3931  if( pos != consdata->nvars - 1 )
3932  {
3933  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3934  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3935 
3936  if( consdata->eventdata != NULL )
3937  {
3938  consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3939  assert(consdata->eventdata[pos] != NULL);
3940  consdata->eventdata[pos]->varpos = pos;
3941  }
3942 
3943  consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3944  consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3945  }
3946  consdata->nvars--;
3947 
3948  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3949  * of the remaining variable, or give exactly 0.0)
3950  */
3951  if( consdata->nvars <= 1 )
3952  consdataInvalidateActivities(consdata);
3953  else
3954  {
3955  if( SCIPconsIsTransformed(cons) )
3956  {
3957  /* if we are in transformed problem, update minimum and maximum activities */
3958  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3959 
3960  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3961  * delta needs to be recalculated on the next real propagation
3962  */
3963  if( consdata->maxactdeltavar == var )
3964  {
3965  consdata->maxactdelta = SCIP_INVALID;
3966  consdata->maxactdeltavar = NULL;
3967  }
3968  }
3969  }
3970 
3971  /* mark the constraint for propagation */
3972  if( SCIPconsIsTransformed(cons) )
3973  {
3974  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3975  }
3976 
3977  consdata->boundstightened = 0;
3978  consdata->presolved = FALSE;
3979  consdata->validsignature = FALSE;
3980  consdata->changed = TRUE;
3981  consdata->normalized = FALSE;
3982  consdata->upgradetried = FALSE;
3983  consdata->cliquesadded = FALSE;
3984  consdata->implsadded = FALSE;
3985  consdata->rangedrowpropagated = 0;
3986 
3987  /* check if hasnonbinvar flag might be incorrect now */
3988  if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3989  {
3990  consdata->hasnonbinvalid = FALSE;
3991  }
3992 
3993  /* delete coefficient from the LP row */
3994  if( consdata->row != NULL )
3995  {
3996  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3997  }
3998 
3999  /* release variable */
4000  SCIP_CALL( SCIPreleaseVar(scip, &var) );
4001 
4002  return SCIP_OKAY;
4003 }
4004 
4005 /** changes coefficient value at given position of linear constraint data */
4006 static
4008  SCIP* scip, /**< SCIP data structure */
4009  SCIP_CONS* cons, /**< linear constraint */
4010  int pos, /**< position of coefficient to delete */
4011  SCIP_Real newval /**< new value of coefficient */
4012  )
4013 {
4014  SCIP_CONSDATA* consdata;
4015  SCIP_VAR* var;
4016  SCIP_Real val;
4017  SCIP_Bool locked;
4018  int i;
4019 
4020  assert(scip != NULL);
4021  assert(cons != NULL);
4022  assert(!SCIPisZero(scip, newval));
4023 
4024  consdata = SCIPconsGetData(cons);
4025  assert(consdata != NULL);
4026  assert(0 <= pos && pos < consdata->nvars);
4027  assert(!SCIPisZero(scip, newval));
4028 
4029  var = consdata->vars[pos];
4030  val = consdata->vals[pos];
4031  assert(var != NULL);
4032  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
4033 
4034  locked = FALSE;
4035  for( i = 0; i < NLOCKTYPES && !locked; i++ )
4036  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
4037 
4038  /* if necessary, update the rounding locks of the variable */
4039  if( locked && newval * val < 0.0 )
4040  {
4041  assert(SCIPconsIsTransformed(cons));
4042 
4043  /* remove rounding locks for variable with old coefficient */
4044  SCIP_CALL( unlockRounding(scip, cons, var, val) );
4045 
4046  /* install rounding locks for variable with new coefficient */
4047  SCIP_CALL( lockRounding(scip, cons, var, newval) );
4048  }
4049 
4050  /* change the value */
4051  consdata->vals[pos] = newval;
4052 
4053  if( consdata->coefsorted )
4054  {
4055  if( pos > 0 )
4056  consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
4057  if( consdata->coefsorted && pos < consdata->nvars - 1 )
4058  consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
4059  }
4060 
4061  /* update minimum and maximum activities */
4062  if( SCIPconsIsTransformed(cons) )
4063  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
4064 
4065  /* mark the constraint for propagation */
4066  if( SCIPconsIsTransformed(cons) )
4067  {
4068  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
4069  }
4070 
4071  consdata->boundstightened = 0;
4072  consdata->presolved = FALSE;
4073  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
4074  consdata->changed = TRUE;
4075  consdata->normalized = FALSE;
4076  consdata->upgradetried = FALSE;
4077  consdata->cliquesadded = FALSE;
4078  consdata->implsadded = FALSE;
4079  consdata->rangedrowpropagated = 0;
4080 
4081  return SCIP_OKAY;
4082 }
4083 
4084 /** scales a linear constraint with a constant scalar */
4085 static
4087  SCIP* scip, /**< SCIP data structure */
4088  SCIP_CONS* cons, /**< linear constraint to scale */
4089  SCIP_Real scalar /**< value to scale constraint with */
4090  )
4091 {
4092  SCIP_CONSDATA* consdata;
4093  SCIP_Real newval;
4094  SCIP_Real absscalar;
4095  int i;
4096 
4097  assert(scip != NULL);
4098  assert(cons != NULL);
4099 
4100  consdata = SCIPconsGetData(cons);
4101  assert(consdata != NULL);
4102  assert(consdata->row == NULL);
4103  assert(scalar != 1.0);
4104 
4105  if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4106  || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4107  {
4108  SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4109  SCIPconsGetName(cons), scalar);
4110 
4111  return SCIP_OKAY;
4112  }
4113 
4114  /* scale the coefficients */
4115  for( i = consdata->nvars - 1; i >= 0; --i )
4116  {
4117  newval = scalar * consdata->vals[i];
4118 
4119  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4120  * flooring down our new value
4121  */
4122  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4123  newval = SCIPfeasFloor(scip, newval + 0.5);
4124 
4125  if( SCIPisZero(scip, newval) )
4126  {
4127  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4128  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4129  SCIP_CALL( delCoefPos(scip, cons, i) );
4130  }
4131  else
4132  consdata->vals[i] = newval;
4133  }
4134 
4135  /* scale the sides */
4136  if( scalar < 0.0 )
4137  {
4138  SCIP_Real lhs;
4139 
4140  lhs = consdata->lhs;
4141  consdata->lhs = -consdata->rhs;
4142  consdata->rhs = -lhs;
4143  }
4144  absscalar = REALABS(scalar);
4145  if( !SCIPisInfinity(scip, -consdata->lhs) )
4146  {
4147  newval = absscalar * consdata->lhs;
4148 
4149  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4150  * flooring down our new value
4151  */
4152  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4153  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4154  else
4155  consdata->lhs = newval;
4156  }
4157  if( !SCIPisInfinity(scip, consdata->rhs) )
4158  {
4159  newval = absscalar * consdata->rhs;
4160 
4161  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4162  * our new value
4163  */
4164  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4165  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4166  else
4167  consdata->rhs = newval;
4168  }
4169 
4170  consdataInvalidateActivities(consdata);
4171  consdata->cliquesadded = FALSE;
4172  consdata->implsadded = FALSE;
4173 
4174  return SCIP_OKAY;
4175 }
4176 
4177 /** perform deletion of variables in all constraints of the constraint handler */
4178 static
4180  SCIP* scip, /**< SCIP data structure */
4181  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4182  SCIP_CONS** conss, /**< array of constraints */
4183  int nconss /**< number of constraints */
4184  )
4185 {
4186  SCIP_CONSDATA* consdata;
4187  int i;
4188  int v;
4189 
4190  assert(scip != NULL);
4191  assert(conshdlr != NULL);
4192  assert(conss != NULL);
4193  assert(nconss >= 0);
4194  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4195 
4196  /* iterate over all constraints */
4197  for( i = 0; i < nconss; i++ )
4198  {
4199  consdata = SCIPconsGetData(conss[i]);
4200 
4201  /* constraint is marked, that some of its variables were deleted */
4202  if( consdata->varsdeleted )
4203  {
4204  /* iterate over all variables of the constraint and delete them from the constraint */
4205  for( v = consdata->nvars - 1; v >= 0; --v )
4206  {
4207  if( SCIPvarIsDeleted(consdata->vars[v]) )
4208  {
4209  SCIP_CALL( delCoefPos(scip, conss[i], v) );
4210  }
4211  }
4212  consdata->varsdeleted = FALSE;
4213  }
4214  }
4215 
4216  return SCIP_OKAY;
4217 }
4218 
4219 
4220 /** normalizes a linear constraint with the following rules:
4221  * - if all coefficients have them same absolute value, change them to (-)1.0
4222  * - multiplication with +1 or -1:
4223  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4224  * if the current rule doesn't determine the sign):
4225  * 1. the right hand side must not be negative
4226  * 2. the right hand side must not be infinite
4227  * 3. the absolute value of the right hand side must be greater than that of the left hand side
4228  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4229  * 5. multiply with +1
4230  * - rationals to integrals
4231  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4232  * by the smallest common multiple of all denominators to get integral coefficients.
4233  * Forbid large denominators due to numerical stability.
4234  * - division by greatest common divisor
4235  * If all coefficients are integral, divide them by the greatest common divisor.
4236  */
4237 static
4239  SCIP* scip, /**< SCIP data structure */
4240  SCIP_CONS* cons, /**< linear constraint to normalize */
4241  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4242  )
4243 {
4244  SCIP_CONSDATA* consdata;
4245  SCIP_Real* vals;
4246  SCIP_Longint scm;
4247  SCIP_Longint nominator;
4248  SCIP_Longint denominator;
4249  SCIP_Longint gcd;
4250  SCIP_Longint maxmult;
4251  SCIP_Real epsilon;
4252  SCIP_Real feastol;
4253  SCIP_Real maxabsval;
4254  SCIP_Real minabsval;
4255  SCIP_Bool success;
4256  SCIP_Bool onlyintegral;
4257  int nvars;
4258  int mult;
4259  int nposcoeffs;
4260  int nnegcoeffs;
4261  int i;
4262 
4263  assert(scip != NULL);
4264  assert(cons != NULL);
4265  assert(infeasible != NULL);
4266 
4267  *infeasible = FALSE;
4268 
4269  /* we must not change a modifiable constraint in any way */
4270  if( SCIPconsIsModifiable(cons) )
4271  return SCIP_OKAY;
4272 
4273  /* get constraint data */
4274  consdata = SCIPconsGetData(cons);
4275  assert(consdata != NULL);
4276 
4277  /* check, if the constraint is already normalized */
4278  if( consdata->normalized )
4279  return SCIP_OKAY;
4280 
4281  /* get coefficient arrays */
4282  vals = consdata->vals;
4283  nvars = consdata->nvars;
4284  assert(nvars == 0 || vals != NULL);
4285 
4286  if( nvars == 0 )
4287  {
4288  consdata->normalized = TRUE;
4289  return SCIP_OKAY;
4290  }
4291 
4292  assert(vals != NULL);
4293 
4294  /* get maximum and minimum absolute coefficient */
4295  maxabsval = consdataGetMaxAbsval(consdata);
4296  minabsval = consdataGetMinAbsval(consdata);
4297 
4298  /* return if scaling by maxval will eliminate coefficients */
4299  if( SCIPisZero(scip, minabsval/maxabsval) )
4300  return SCIP_OKAY;
4301 
4302  /* return if scaling by maxval will eliminate or generate non-zero sides */
4303  if( !SCIPisInfinity(scip, consdata->lhs) && SCIPisFeasZero(scip, consdata->lhs) != SCIPisFeasZero(scip, consdata->lhs/maxabsval) )
4304  return SCIP_OKAY;
4305  if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasZero(scip, consdata->rhs) != SCIPisFeasZero(scip, consdata->rhs/maxabsval) )
4306  return SCIP_OKAY;
4307 
4308  /* check if not all absolute coefficients are near 1.0 but scaling could do */
4309  if( SCIPisLT(scip, minabsval, 1.0) != SCIPisGT(scip, maxabsval, 1.0) )
4310  {
4311  SCIP_Real scalar;
4312 
4313  /* calculate scale of the average minimum and maximum absolute coefficient to 1.0 */
4314  scalar = 2.0 / (minabsval + maxabsval);
4315 
4316  /* check if all scaled absolute coefficients are near 1.0
4317  * we can relax EQ(x,1.0) to LE(x,1.0), as LT(x,1.0) is not possible
4318  */
4319  if( SCIPisLE(scip, scalar * maxabsval, 1.0) )
4320  {
4321  SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4322  SCIPdebugPrintCons(scip, cons, NULL);
4323  SCIP_CALL( scaleCons(scip, cons, scalar) );
4324 
4325  /* get new consdata information, because scaleCons() might have deleted variables */
4326  vals = consdata->vals;
4327  nvars = consdata->nvars;
4328 
4329  assert(nvars == 0 || vals != NULL);
4330  }
4331  }
4332 
4333  /* nvars might have changed */
4334  if( nvars == 0 )
4335  {
4336  consdata->normalized = TRUE;
4337  return SCIP_OKAY;
4338  }
4339 
4340  assert(vals != NULL);
4341 
4342  /* calculate the maximal multiplier for common divisor calculation:
4343  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4344  * which means, a value of feastol/epsilon should be used as maximal multiplier;
4345  * additionally, we don't want to scale the constraint if this would lead to too
4346  * large coefficients
4347  */
4348  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4349  feastol = SCIPfeastol(scip);
4350  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4351 
4352  if( !consdata->hasnonbinvalid )
4353  consdataCheckNonbinvar(consdata);
4354 
4355  /* get maximum absolute coefficient */
4356  maxabsval = consdataGetMaxAbsval(consdata);
4357 
4358  /* if all variables are of integral type we will allow a greater multiplier */
4359  if( !consdata->hascontvar )
4360  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4361  else
4362  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4363 
4364  /*
4365  * multiplication with +1 or -1
4366  */
4367  mult = 0;
4368 
4369  /* 1. the right hand side must not be negative */
4370  if( SCIPisPositive(scip, consdata->lhs) )
4371  mult = +1;
4372  else if( SCIPisNegative(scip, consdata->rhs) )
4373  mult = -1;
4374 
4375  if( mult == 0 )
4376  {
4377  /* 2. the right hand side must not be infinite */
4378  if( SCIPisInfinity(scip, -consdata->lhs) )
4379  mult = +1;
4380  else if( SCIPisInfinity(scip, consdata->rhs) )
4381  mult = -1;
4382  }
4383 
4384  if( mult == 0 )
4385  {
4386  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4387  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4388  mult = +1;
4389  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4390  mult = -1;
4391  }
4392 
4393  if( mult == 0 )
4394  {
4395  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4396  nposcoeffs = 0;
4397  nnegcoeffs = 0;
4398  for( i = 0; i < nvars; ++i )
4399  {
4400  if( vals[i] > 0.0 )
4401  nposcoeffs++;
4402  else
4403  nnegcoeffs++;
4404  }
4405  if( nposcoeffs > nnegcoeffs )
4406  mult = +1;
4407  else if( nposcoeffs < nnegcoeffs )
4408  mult = -1;
4409  }
4410 
4411  if( mult == 0 )
4412  {
4413  /* 5. multiply with +1 */
4414  mult = +1;
4415  }
4416 
4417  assert(mult == +1 || mult == -1);
4418  if( mult == -1 )
4419  {
4420  /* scale the constraint with -1 */
4421  SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4422  SCIPdebugPrintCons(scip, cons, NULL);
4423  SCIP_CALL( scaleCons(scip, cons, -1.0) );
4424 
4425  /* scalecons() can delete variables, but scaling with -1 should not do that */
4426  assert(nvars == consdata->nvars);
4427  }
4428 
4429  /*
4430  * rationals to integrals
4431  *
4432  * @todo try scaling only on behalf of non-continuous variables
4433  */
4434  success = TRUE;
4435  scm = 1;
4436  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4437  {
4438  if( !SCIPisIntegral(scip, vals[i]) )
4439  {
4440  /* epsilon has been slightly decreased above - to be on the safe side */
4441  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4442  if( success )
4443  scm = SCIPcalcSmaComMul(scm, denominator);
4444  }
4445  }
4446  assert(scm >= 1);
4447 
4448  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4449  * their greatest common divisor
4450  */
4451  onlyintegral = TRUE;
4452  if( scm == 1 )
4453  {
4454  for( i = nvars - 1; i >= 0; --i )
4455  {
4456  if( !SCIPisIntegral(scip, vals[i]) )
4457  {
4458  onlyintegral = FALSE;
4459  break;
4460  }
4461  }
4462  }
4463 
4464  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4465  if( success && scm != 1 )
4466  {
4467  /* scale the constraint with the smallest common multiple of all denominators */
4468  SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4469  SCIPdebugPrintCons(scip, cons, NULL);
4470  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4471 
4472  if( consdata->validmaxabsval )
4473  {
4474  consdata->maxabsval *= REALABS((SCIP_Real)scm);
4475  if( !SCIPisIntegral(scip, consdata->maxabsval) )
4476  {
4477  consdata->validmaxabsval = FALSE;
4478  consdata->maxabsval = SCIP_INVALID;
4479  consdataCalcMaxAbsval(consdata);
4480  }
4481  }
4482 
4483  if( consdata->validminabsval )
4484  {
4485  consdata->minabsval *= REALABS((SCIP_Real)scm);
4486  if( !SCIPisIntegral(scip, consdata->minabsval) )
4487  {
4488  consdata->validminabsval = FALSE;
4489  consdata->minabsval = SCIP_INVALID;
4490  consdataCalcMinAbsval(consdata);
4491  }
4492  }
4493 
4494  /* get new consdata information, because scalecons() might have deleted variables */
4495  vals = consdata->vals;
4496  nvars = consdata->nvars;
4497  assert(nvars == 0 || vals != NULL);
4498  }
4499 
4500  /*
4501  * division by greatest common divisor
4502  */
4503  if( success && nvars >= 1 )
4504  {
4505  /* all coefficients are integral: divide them by their greatest common divisor */
4506  assert(SCIPisIntegral(scip, vals[0]));
4507 
4508  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4509  for( i = 1; i < nvars && gcd > 1; ++i )
4510  {
4511  assert(SCIPisIntegral(scip, vals[i]));
4512  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4513  }
4514 
4515  if( gcd > 1 )
4516  {
4517  /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4518  if( !consdata->hascontvar && onlyintegral )
4519  {
4520  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4521  {
4522  *infeasible = TRUE;
4523 
4524  SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4525  SCIPdebugPrintCons(scip, cons, NULL);
4526 
4527  return SCIP_OKAY;
4528  }
4529  }
4530 
4531  /* divide the constraint by the greatest common divisor of the coefficients */
4532  SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4533  SCIPdebugPrintCons(scip, cons, NULL);
4534  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4535 
4536  if( consdata->validmaxabsval )
4537  {
4538  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4539  }
4540  if( consdata->validminabsval )
4541  {
4542  consdata->minabsval /= REALABS((SCIP_Real)gcd);
4543  }
4544  }
4545  }
4546 
4547  /* mark constraint to be normalized */
4548  consdata->normalized = TRUE;
4549 
4550  SCIPdebugMsg(scip, "normalized constraint:\n");
4551  SCIPdebugPrintCons(scip, cons, NULL);
4552 
4553  return SCIP_OKAY;
4554 }
4555 
4556 /** replaces multiple occurrences of a variable by a single coefficient */
4557 static
4559  SCIP* scip, /**< SCIP data structure */
4560  SCIP_CONS* cons /**< linear constraint */
4561  )
4562 {
4563  SCIP_CONSDATA* consdata;
4564  SCIP_VAR* var;
4565  SCIP_Real valsum;
4566  int v;
4567 
4568  assert(scip != NULL);
4569  assert(cons != NULL);
4570 
4571  consdata = SCIPconsGetData(cons);
4572  assert(consdata != NULL);
4573 
4574  if( consdata->merged )
4575  return SCIP_OKAY;
4576 
4577  /* sort the constraint */
4578  SCIP_CALL( consdataSort(scip, consdata) );
4579 
4580  /* go backwards through the constraint looking for multiple occurrences of the same variable;
4581  * backward direction is necessary, since delCoefPos() modifies the given position and
4582  * the subsequent ones
4583  */
4584  v = consdata->nvars-1;
4585  while( v >= 1 )
4586  {
4587  var = consdata->vars[v];
4588  if( consdata->vars[v-1] == var )
4589  {
4590  valsum = consdata->vals[v];
4591  do
4592  {
4593  SCIP_CALL( delCoefPos(scip, cons, v) );
4594  --v;
4595  valsum += consdata->vals[v];
4596  }
4597  while( v >= 1 && consdata->vars[v-1] == var );
4598 
4599  /* modify the last existing occurrence of the variable */
4600  assert(consdata->vars[v] == var);
4601  if( SCIPisZero(scip, valsum) )
4602  {
4603  SCIP_CALL( delCoefPos(scip, cons, v) );
4604 
4605  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4606  * delta needs to be recalculated on the next real propagation
4607  */
4608  if( consdata->maxactdeltavar == var )
4609  {
4610  consdata->maxactdelta = SCIP_INVALID;
4611  consdata->maxactdeltavar = NULL;
4612  }
4613  }
4614  else
4615  {
4616  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4617  }
4618  }
4619  --v;
4620  }
4621 
4622  consdata->merged = TRUE;
4623 
4624  return SCIP_OKAY;
4625 }
4626 
4627 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4628 static
4630  SCIP* scip, /**< SCIP data structure */
4631  SCIP_CONS* cons, /**< linear constraint */
4632  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4633  * information is not needed; in this case, we apply all fixings
4634  * instead of stopping after the first infeasible one */
4635  )
4636 {
4637  SCIP_CONSDATA* consdata;
4638  SCIP_VAR* var;
4639  SCIP_VAR** aggrvars;
4640  SCIP_Real val;
4641  SCIP_Real* aggrscalars;
4642  SCIP_Real fixedval;
4643  SCIP_Real aggrconst;
4644  int v;
4645  int naggrvars;
4646  int i;
4647 
4648  assert(scip != NULL);
4649  assert(cons != NULL);
4650 
4651  if( infeasible != NULL )
4652  *infeasible = FALSE;
4653 
4654  consdata = SCIPconsGetData(cons);
4655  assert(consdata != NULL);
4656 
4657  if( consdata->eventdata == NULL )
4658  {
4659  SCIP_CONSHDLR* conshdlr;
4660  SCIP_CONSHDLRDATA* conshdlrdata;
4661 
4662  conshdlr = SCIPconsGetHdlr(cons);
4663  assert(conshdlr != NULL);
4664 
4665  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4666  assert(conshdlrdata != NULL);
4667 
4668  /* catch bound change events of variables */
4669  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4670  assert(consdata->eventdata != NULL);
4671  }
4672 
4673  if( !consdata->removedfixings )
4674  {
4675  SCIP_Real lhssubtrahend;
4676  SCIP_Real rhssubtrahend;
4677 
4678  /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4679  * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4680  */
4681  assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4682 
4683  lhssubtrahend = 0.0;
4684  rhssubtrahend = 0.0;
4685 
4686  SCIPdebugMsg(scip, "applying fixings:\n");
4687  SCIPdebugPrintCons(scip, cons, NULL);
4688 
4689  v = 0;
4690  while( v < consdata->nvars )
4691  {
4692  var = consdata->vars[v];
4693  val = consdata->vals[v];
4694  assert(SCIPvarIsTransformed(var));
4695 
4696  switch( SCIPvarGetStatus(var) )
4697  {
4699  SCIPerrorMessage("original variable in transformed linear constraint\n");
4700  return SCIP_INVALIDDATA;
4701 
4702  case SCIP_VARSTATUS_LOOSE:
4703  case SCIP_VARSTATUS_COLUMN:
4704  ++v;
4705  break;
4706 
4707  case SCIP_VARSTATUS_FIXED:
4708  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4709  fixedval = SCIPvarGetLbGlobal(var);
4710  if( !SCIPisInfinity(scip, -consdata->lhs) )
4711  {
4712  if( SCIPisInfinity(scip, ABS(fixedval)) )
4713  {
4714  /* if lhs gets infinity it means that the problem is infeasible */
4715  if( ( val > 0.0 ) != ( fixedval > 0.0 ) )
4716  {
4717  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4718 
4719  if( infeasible != NULL )
4720  {
4721  *infeasible = TRUE;
4722  return SCIP_OKAY;
4723  }
4724  }
4725  else
4726  {
4727  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4728  }
4729  }
4730  else
4731  lhssubtrahend += val * fixedval;
4732  }
4733  if( !SCIPisInfinity(scip, consdata->rhs) )
4734  {
4735  if( SCIPisInfinity(scip, ABS(fixedval)) )
4736  {
4737  /* if rhs gets -infinity it means that the problem is infeasible */
4738  if( ( val > 0.0 ) == ( fixedval > 0.0 ) )
4739  {
4740  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4741 
4742  if( infeasible != NULL )
4743  {
4744  *infeasible = TRUE;
4745  return SCIP_OKAY;
4746  }
4747  }
4748  else
4749  {
4750  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4751  }
4752  }
4753  else
4754  rhssubtrahend += val * fixedval;
4755  }
4756  SCIP_CALL( delCoefPos(scip, cons, v) );
4757  break;
4758 
4760  {
4761  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4762  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4763  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4764 
4765  assert(activevar != NULL);
4766  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4767  assert(activevar != NULL);
4768 
4769  if( !SCIPisZero(scip, activescalar) )
4770  {
4771  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4772  }
4773 
4774  if( !SCIPisZero(scip, activeconstant) )
4775  {
4776  if( !SCIPisInfinity(scip, -consdata->lhs) )
4777  lhssubtrahend += activeconstant;
4778  if( !SCIPisInfinity(scip, consdata->rhs) )
4779  rhssubtrahend += activeconstant;
4780  }
4781 
4782  SCIP_CALL( delCoefPos(scip, cons, v) );
4783  break;
4784  }
4787  naggrvars = SCIPvarGetMultaggrNVars(var);
4788  aggrvars = SCIPvarGetMultaggrVars(var);
4789  aggrscalars = SCIPvarGetMultaggrScalars(var);
4790  for( i = 0; i < naggrvars; ++i )
4791  {
4792  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4793  }
4794  aggrconst = SCIPvarGetMultaggrConstant(var);
4795 
4796  if( !SCIPisInfinity(scip, -consdata->lhs) )
4797  lhssubtrahend += val * aggrconst;
4798  if( !SCIPisInfinity(scip, consdata->rhs) )
4799  rhssubtrahend += val * aggrconst;
4800 
4801  SCIP_CALL( delCoefPos(scip, cons, v) );
4802  break;
4803 
4805  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4806  aggrconst = SCIPvarGetNegationConstant(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 
4816  default:
4817  SCIPerrorMessage("unknown variable status\n");
4818  SCIPABORT();
4819  return SCIP_INVALIDDATA; /*lint !e527*/
4820  }
4821  }
4822 
4823  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4824  {
4825  /* check left hand side of unmodifiable empty constraint with former feasibility tolerance */
4826  if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4827  {
4828  if( SCIPisFeasLT(scip, lhssubtrahend, consdata->lhs) )
4829  {
4830  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4831 
4832  if( infeasible != NULL )
4833  {
4834  *infeasible = TRUE;
4835  return SCIP_OKAY;
4836  }
4837  }
4838  else
4839  {
4840  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4841  }
4842  }
4843  /* for large numbers that are relatively equal, subtraction can lead to cancellation,
4844  * causing wrong fixings of other variables --> better use a real zero here
4845  */
4846  else if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) )
4847  {
4848  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4849  }
4850  else
4851  {
4852  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4853  }
4854  }
4855  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs) )
4856  {
4857  /* check right hand side of unmodifiable empty constraint with former feasibility tolerance */
4858  if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4859  {
4860  if( SCIPisFeasGT(scip, rhssubtrahend, consdata->rhs) )
4861  {
4862  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4863 
4864  if( infeasible != NULL )
4865  {
4866  *infeasible = TRUE;
4867  return SCIP_OKAY;
4868  }
4869  }
4870  else
4871  {
4872  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4873  }
4874  }
4875  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4876  * causing wrong fixings of other variables --> better use a real zero here
4877  */
4878  else if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs) )
4879  {
4880  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4881  }
4882  else
4883  {
4884  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4885  }
4886  }
4887  consdata->removedfixings = TRUE;
4888 
4889  SCIPdebugMsg(scip, "after fixings:\n");
4890  SCIPdebugPrintCons(scip, cons, NULL);
4891 
4892  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4893  * to clean up the constraint
4894  */
4895  SCIP_CALL( mergeMultiples(scip, cons) );
4896 
4897  SCIPdebugMsg(scip, "after merging:\n");
4898  SCIPdebugPrintCons(scip, cons, NULL);
4899  }
4900  assert(consdata->removedfixings);
4901 
4902 #ifndef NDEBUG
4903  /* check, if all fixings are applied */
4904  for( v = 0; v < consdata->nvars; ++v )
4905  assert(SCIPvarIsActive(consdata->vars[v]));
4906 #endif
4907 
4908  return SCIP_OKAY;
4909 }
4910 
4911 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4912  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4913  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4914  * conflict detecting constraint by using NULL as inferred variable
4915  */
4916 static
4918  SCIP* scip, /**< SCIP data structure */
4919  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4920  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4921  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4922  int inferpos, /**< position of the inferred variable in the vars array */
4923  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4924  )
4925 {
4926  SCIP_CONSDATA* consdata;
4927  SCIP_VAR** vars;
4928  SCIP_Real* vals;
4929  int nvars;
4930  int i;
4931 
4932  assert(scip != NULL);
4933  assert(cons != NULL);
4934 
4935  consdata = SCIPconsGetData(cons);
4937  assert(consdata != NULL);
4938 
4939  vars = consdata->vars;
4940  vals = consdata->vals;
4941  nvars = consdata->nvars;
4942 
4943  assert(vars != NULL || nvars == 0);
4944  assert(vals != NULL || nvars == 0);
4945 
4946  assert(-1 <= inferpos && inferpos < nvars);
4947  assert((infervar == NULL) == (inferpos == -1));
4948  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4949 
4950  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4951  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4952  * - if the right hand side is the reason, the minimal residual activity is responsible
4953  * - if the left hand side is the reason, the maximal residual activity is responsible
4954  */
4955 
4956  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4957  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4958  {
4959  SCIP_Real minresactivity;
4960  SCIP_Real maxresactivity;
4961  SCIP_Bool ismintight;
4962  SCIP_Bool ismaxtight;
4963  SCIP_Bool isminsettoinfinity;
4964  SCIP_Bool ismaxsettoinfinity;
4965 
4966  minresactivity = -SCIPinfinity(scip);
4967  maxresactivity = SCIPinfinity(scip);
4968 
4969  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4970  if( infervar != NULL )
4971  {
4972  assert(vals != NULL); /* for flexelint */
4973  if( reasonisrhs )
4974  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4975  &ismintight, NULL, &isminsettoinfinity, NULL);
4976  else
4977  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4978  NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4979  }
4980  else
4981  {
4982  if( reasonisrhs )
4983  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4984  &ismintight, NULL, &isminsettoinfinity, NULL);
4985  else
4986  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4987  NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4988  }
4989 
4990  /* we can only do something clever, if the residual activity is finite and not relaxed */
4991  if( (reasonisrhs && !isminsettoinfinity && ismintight) || (!reasonisrhs && !ismaxsettoinfinity && ismaxtight) ) /*lint !e644*/
4992  {
4993  SCIP_Real rescap;
4994  SCIP_Bool resactisinf;
4995 
4996  resactisinf = FALSE;
4997 
4998  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4999  * than its inferred bound
5000  */
5001  if( infervar != NULL )
5002  {
5003  assert(vals != NULL); /* for flexelint */
5004 
5005  if( reasonisrhs )
5006  {
5007  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
5008  {
5009  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
5010  if( SCIPisInfinity(scip, -minresactivity) )
5011  resactisinf = TRUE;
5012  }
5013  rescap = consdata->rhs - minresactivity;
5014  }
5015  else
5016  {
5017  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
5018  {
5019  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
5020  if( SCIPisInfinity(scip, maxresactivity) )
5021  resactisinf = TRUE;
5022  }
5023  rescap = consdata->lhs - maxresactivity;
5024  }
5025 
5026  if( reasonisrhs == (vals[inferpos] > 0.0) )
5027  rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
5028  else
5029  rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
5030  }
5031  else
5032  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
5033 
5034  if( !resactisinf )
5035  {
5036  /* now add bounds as reasons until the residual capacity is exceeded */
5037  for( i = 0; i < nvars; ++i )
5038  {
5039  assert( vars != NULL && vals != NULL ); /* for lint */
5040 
5041  /* zero coefficients and the inferred variable can be ignored */
5042  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5043  continue;
5044 
5045  /* check if the residual capacity is exceeded */
5046  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
5047  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
5048  break;
5049 
5050  /* update the residual capacity due to the local bound of this variable */
5051  if( reasonisrhs == (vals[i] > 0.0) )
5052  {
5053  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
5054  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5055  rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
5056  }
5057  else
5058  {
5059  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
5060  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5061  rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
5062  }
5063  }
5064  return SCIP_OKAY;
5065  }
5066  }
5067  }
5068 
5069  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
5070  for( i = 0; i < nvars; ++i )
5071  {
5072  assert(vars != NULL); /* for flexelint */
5073  assert(vals != NULL); /* for flexelint */
5074 
5075  /* zero coefficients and the inferred variable can be ignored */
5076  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5077  continue;
5078 
5079  if( reasonisrhs == (vals[i] > 0.0) )
5080  {
5081  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
5082  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5083  }
5084  else
5085  {
5086  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
5087  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5088  }
5089  }
5090 
5091  return SCIP_OKAY;
5092 }
5093 
5094 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
5095  * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
5096  * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
5097  */
5098 static
5100  SCIP* scip, /**< SCIP data structure */
5101  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5102  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
5103  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5104  int inferpos /**< position of the inferred variable in the vars array, or -1 */
5105  )
5106 {
5107  SCIP_CONSDATA* consdata;
5108  SCIP_VAR** vars;
5109  int nvars;
5110  int v;
5111 
5112  assert(scip != NULL);
5113  assert(cons != NULL);
5114 
5115  consdata = SCIPconsGetData(cons);
5116  assert(consdata != NULL);
5117  vars = consdata->vars;
5118  nvars = consdata->nvars;
5119  assert(vars != NULL || nvars == 0);
5120  assert(-1 <= inferpos && inferpos < nvars);
5121  assert((infervar == NULL) == (inferpos == -1));
5122  assert(inferpos == -1 || vars != NULL);
5123  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5124 
5125  /* collect all fixed variables */
5126  for( v = nvars - 1; v >= 0; --v )
5127  {
5128  assert(vars != NULL); /* for flexelint */
5129 
5130  /* need to add old bounds before propagation of inferrence variable */
5131  if( vars[v] == infervar )
5132  {
5133  assert(vars[v] != NULL);
5134 
5135  if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5136  {
5137  /* @todo get boundchange index before this last boundchange and correct the index */
5138  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5139  }
5140 
5141  if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5142  {
5143  /* @todo get boundchange index before this last boundchange and correct the index */
5144  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5145  }
5146 
5147  continue;
5148  }
5149 
5150  /* check for fixed variables */
5151  if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5152  {
5153  /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5154  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5155  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5156  }
5157  }
5158 
5159  return SCIP_OKAY;
5160 }
5161 
5162 /** add reasoning variables to conflict candidate queue which led to the conflict */
5163 static
5165  SCIP* scip, /**< SCIP data structure */
5166  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5167  int nvars, /**< number of variables reasoning the infeasibility */
5168  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5169  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5170  )
5171 {
5172  int v;
5173 
5174  assert(scip != NULL);
5175 
5176  /* collect all variables for which the local bounds differ from their global bounds */
5177  for( v = nvars - 1; v >= 0; --v )
5178  {
5179  assert(vars != NULL);
5180 
5181  /* check for local bound changes variables */
5182  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5183  {
5184  /* add conflict bound */
5185  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5186  }
5187 
5188  if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5189  {
5190  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5191  }
5192  }
5193 
5194  if( var != NULL )
5195  {
5196  if( bound < SCIPvarGetLbLocal(var) )
5197  {
5198  SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5199  }
5200 
5201  if( bound > SCIPvarGetUbLocal(var) )
5202  {
5203  SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5204  }
5205  }
5206 
5207  return SCIP_OKAY;
5208 }
5209 
5210 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5211  * propagation rule (see propagateCons()):
5212  * (1) activity residuals of all other variables tighten bounds of single variable
5213  */
5214 static
5216  SCIP* scip, /**< SCIP data structure */
5217  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5218  SCIP_VAR* infervar, /**< variable that was deduced */
5219  INFERINFO inferinfo, /**< inference information */
5220  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5221  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5222  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5223  )
5224 {
5225  SCIP_CONSDATA* consdata;
5226  SCIP_VAR** vars;
5227 #ifndef NDEBUG
5228  SCIP_Real* vals;
5229 #endif
5230  int nvars;
5231  int inferpos;
5232 
5233  assert(scip != NULL);
5234  assert(cons != NULL);
5235  assert(result != NULL);
5236 
5237  consdata = SCIPconsGetData(cons);
5238  assert(consdata != NULL);
5239  vars = consdata->vars;
5240  nvars = consdata->nvars;
5241 #ifndef NDEBUG
5242  vals = consdata->vals;
5243  assert(vars != NULL);
5244  assert(vals != NULL);
5245 #endif
5246 
5247  /* get the position of the inferred variable in the vars array */
5248  inferpos = inferInfoGetPos(inferinfo);
5249  if( inferpos >= nvars || vars[inferpos] != infervar )
5250  {
5251  /* find inference variable in constraint */
5252  /**@todo use a binary search here; the variables can be sorted by variable index */
5253  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5254  {}
5255  }
5256  assert(inferpos < nvars);
5257  assert(vars[inferpos] == infervar);
5258  assert(!SCIPisZero(scip, vals[inferpos]));
5259 
5260  switch( inferInfoGetProprule(inferinfo) )
5261  {
5262  case PROPRULE_1_RHS:
5263  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5264  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5265  * domain in order to not exceed the right hand side of the inequality
5266  */
5267  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5268  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5269  *result = SCIP_SUCCESS;
5270  break;
5271 
5272  case PROPRULE_1_LHS:
5273  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5274  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5275  * domain in order to not fall below the left hand side of the inequality
5276  */
5277  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5278  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5279  *result = SCIP_SUCCESS;
5280  break;
5281 
5282  case PROPRULE_1_RANGEDROW:
5283  /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5284  * the given inference variable to their bounds in this given ranged row
5285  */
5286 
5287  /* check that we really have a ranged row here */
5288  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5289  SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5290  *result = SCIP_SUCCESS;
5291  break;
5292 
5293  case PROPRULE_INVALID:
5294  default:
5295  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5296  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5297  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5298  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5299  SCIPinfoMessage(scip, NULL, ";\n");
5300  return SCIP_INVALIDDATA;
5301  }
5302 
5303  return SCIP_OKAY;
5304 }
5305 
5306 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5307 static
5309  SCIP* scip, /**< SCIP data structure */
5310  SCIP_CONS* cons, /**< conflict detecting constraint */
5311  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5312  )
5313 {
5314  /* conflict analysis can only be applied in solving stage and if it is turned on */
5316  return SCIP_OKAY;
5317 
5318  /* initialize conflict analysis */
5320 
5321  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5322  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5323 
5324  /* analyze the conflict */
5325  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5326 
5327  return SCIP_OKAY;
5328 }
5329 
5330 /** check if there is any hope of tightening some bounds */
5331 static
5333  SCIP_CONS* cons /**< linear constraint */
5334  )
5335 {
5336  SCIP_CONSDATA* consdata;
5337  int infcountmin;
5338  int infcountmax;
5339 
5340  consdata = SCIPconsGetData(cons);
5341  assert(consdata != NULL);
5342 
5343  infcountmin = consdata->minactivityneginf
5344  + consdata->minactivityposinf
5345  + consdata->minactivityneghuge
5346  + consdata->minactivityposhuge;
5347  infcountmax = consdata->maxactivityneginf
5348  + consdata->maxactivityposinf
5349  + consdata->maxactivityneghuge
5350  + consdata->maxactivityposhuge;
5352  if( infcountmin > 1 && infcountmax > 1 )
5353  return FALSE;
5354 
5355  return TRUE;
5356 }
5357 
5358 /** tighten upper bound */
5359 static
5361  SCIP* scip, /**< SCIP data structure */
5362  SCIP_CONS* cons, /**< linear constraint */
5363  int pos, /**< variable position */
5364  PROPRULE proprule, /**< propagation rule that deduced the value */
5365  SCIP_Real newub, /**< new upper bound */
5366  SCIP_Real oldub, /**< old upper bound */
5367  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5368  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5369  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5370  )
5371 {
5372  SCIP_CONSDATA* consdata;
5373  SCIP_VAR* var;
5374  SCIP_Real lb;
5375  SCIP_Bool infeasible;
5376  SCIP_Bool tightened;
5377 
5378  assert(cons != NULL);
5379  assert(!SCIPisInfinity(scip, newub));
5380 
5381  consdata = SCIPconsGetData(cons);
5382  assert(consdata != NULL);
5383  var = consdata->vars[pos];
5384  assert(var != NULL);
5385 
5386  lb = SCIPvarGetLbLocal(var);
5387  newub = SCIPadjustedVarUb(scip, var, newub);
5388 
5389  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5390  {
5391  SCIP_VARTYPE vartype;
5392 
5393  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5394  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5395  QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5396 
5397  vartype = SCIPvarGetType(var);
5398 
5399  /* tighten upper bound */
5400  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5401 
5402  if( infeasible )
5403  {
5404  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5405  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5406 
5407  /* analyze conflict */
5408  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5409 
5410  *cutoff = TRUE;
5411  }
5412  else if( tightened )
5413  {
5414  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5415  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5416  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5417 
5418  (*nchgbds)++;
5419 
5420  /* if variable type was changed we might be able to upgrade the constraint */
5421  if( vartype != SCIPvarGetType(var) )
5422  consdata->upgradetried = FALSE;
5423  }
5424  }
5425  return SCIP_OKAY;
5426 }
5427 
5428 /** tighten lower bound */
5429 static
5431  SCIP* scip, /**< SCIP data structure */
5432  SCIP_CONS* cons, /**< linear constraint */
5433  int pos, /**< variable position */
5434  PROPRULE proprule, /**< propagation rule that deduced the value */
5435  SCIP_Real newlb, /**< new lower bound */
5436  SCIP_Real oldlb, /**< old lower bound */
5437  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5438  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5439  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5440  )
5441 {
5442  SCIP_CONSDATA* consdata;
5443  SCIP_VAR* var;
5444  SCIP_Real ub;
5445  SCIP_Bool infeasible;
5446  SCIP_Bool tightened;
5447 
5448  assert(cons != NULL);
5449  assert(!SCIPisInfinity(scip, newlb));
5450 
5451  consdata = SCIPconsGetData(cons);
5452  assert(consdata != NULL);
5453  var = consdata->vars[pos];
5454  assert(var != NULL);
5455 
5456  ub = SCIPvarGetUbLocal(var);
5457  newlb = SCIPadjustedVarLb(scip, var, newlb);
5458 
5459  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5460  {
5461  SCIP_VARTYPE vartype;
5462 
5463  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5464  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5465  QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5466 
5467  vartype = SCIPvarGetType(var);
5468 
5469  /* tighten lower bound */
5470  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5471 
5472  if( infeasible )
5473  {
5474  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5475  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5476 
5477  /* analyze conflict */
5478  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5479 
5480  *cutoff = TRUE;
5481  }
5482  else if( tightened )
5483  {
5484  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5485  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5486  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5487 
5488  (*nchgbds)++;
5489 
5490  /* if variable type was changed we might be able to upgrade the constraint */
5491  if( vartype != SCIPvarGetType(var) )
5492  consdata->upgradetried = FALSE;
5493  }
5494  }
5495  return SCIP_OKAY;
5496 }
5497 
5498 /** tightens bounds of a single variable due to activity bounds (easy case) */
5499 static
5501  SCIP* scip, /**< SCIP data structure */
5502  SCIP_CONS* cons, /**< linear constraint */
5503  int pos, /**< position of the variable in the vars array */
5504  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5505  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5506  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5507  )
5508 {
5509  SCIP_CONSDATA* consdata;
5510  SCIP_VAR* var;
5511  SCIP_Real val;
5512  SCIP_Real lb;
5513  SCIP_Real ub;
5514  SCIP_Real lhs;
5515  SCIP_Real rhs;
5516 
5517  assert(scip != NULL);
5518  assert(cons != NULL);
5519  assert(cutoff != NULL);
5520  assert(nchgbds != NULL);
5521 
5522  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5523  if( SCIPconsIsModifiable(cons) )
5524  return SCIP_OKAY;
5525 
5526  consdata = SCIPconsGetData(cons);
5527  assert(consdata != NULL);
5528  assert(0 <= pos && pos < consdata->nvars);
5529 
5530  *cutoff = FALSE;
5531 
5532  var = consdata->vars[pos];
5533  assert(var != NULL);
5534 
5535  /* we cannot tighten bounds of multi-aggregated variables */
5537  return SCIP_OKAY;
5538 
5539  val = consdata->vals[pos];
5540  lhs = consdata->lhs;
5541  rhs = consdata->rhs;
5542  assert(!SCIPisZero(scip, val));
5543  assert(!SCIPisInfinity(scip, lhs));
5544  assert(!SCIPisInfinity(scip, -rhs));
5545 
5546  lb = SCIPvarGetLbLocal(var);
5547  ub = SCIPvarGetUbLocal(var);
5548  assert(SCIPisLE(scip, lb, ub));
5549 
5550  /* recompute activities if needed */
5551  if( !consdata->validactivities )
5552  consdataCalcActivities(scip, consdata);
5553  assert(consdata->validactivities);
5554  if( !consdata->validminact )
5555  consdataRecomputeMinactivity(scip, consdata);
5556  assert(consdata->validminact);
5557 
5558  if( val > 0.0 )
5559  {
5560  /* check, if we can tighten the variable's upper bound */
5561  if( !SCIPisInfinity(scip, rhs) )
5562  {
5563  SCIP_Real slack;
5564  SCIP_Real alpha;
5565 
5566  /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5567  assert(consdata->validminact);
5568 
5569  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5570  if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5571  {
5572  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5573  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5574 
5575  *cutoff = TRUE;
5576  return SCIP_OKAY;
5577  }
5578 
5579  slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5580 
5581  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5582  * it to zero
5583  */
5584  if( !SCIPisPositive(scip, slack) )
5585  slack = 0.0;
5586 
5587  alpha = val * (ub - lb);
5588  assert(!SCIPisNegative(scip, alpha));
5589 
5590  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5591  {
5592  SCIP_Real newub;
5593 
5594  /* compute new upper bound */
5595  newub = lb + (slack / val);
5596 
5597  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5598 
5599  if( *cutoff )
5600  {
5601  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5602  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5603 
5604  return SCIP_OKAY;
5605  }
5606 
5607  /* collect the new upper bound which is needed for the lower bound computation */
5608  ub = SCIPvarGetUbLocal(var);
5609  }
5610  }
5611 
5612  /* check, if we can tighten the variable's lower bound */
5613  if( !SCIPisInfinity(scip, -lhs) )
5614  {
5615  SCIP_Real slack;
5616  SCIP_Real alpha;
5617 
5618  /* make sure the max activity is reliable */
5619  if( !consdata->validmaxact )
5620  {
5621  consdataRecomputeMaxactivity(scip, consdata);
5622  }
5623  assert(consdata->validmaxact);
5624 
5625  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5626  if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5627  {
5628  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5629  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5630 
5631  *cutoff = TRUE;
5632  return SCIP_OKAY;
5633  }
5634 
5635  slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5636 
5637  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5638  * it to zero
5639  */
5640  if( !SCIPisPositive(scip, slack) )
5641  slack = 0.0;
5642 
5643  alpha = val * (ub - lb);
5644  assert(!SCIPisNegative(scip, alpha));
5645 
5646  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5647  {
5648  SCIP_Real newlb;
5649 
5650  /* compute new lower bound */
5651  newlb = ub - (slack / val);
5652 
5653  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5654 
5655  if( *cutoff )
5656  {
5657  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5658  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5659 
5660  return SCIP_OKAY;
5661  }
5662  }
5663  }
5664  }
5665  else
5666  {
5667  /* check, if we can tighten the variable's lower bound */
5668  if( !SCIPisInfinity(scip, rhs) )
5669  {
5670  SCIP_Real slack;
5671  SCIP_Real alpha;
5672 
5673  /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5674  assert(consdata->validminact);
5675 
5676  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5677  if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5678  {
5679  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5680  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5681 
5682  *cutoff = TRUE;
5683  return SCIP_OKAY;
5684  }
5685 
5686  slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5687 
5688  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5689  * it to zero
5690  */
5691  if( !SCIPisPositive(scip, slack) )
5692  slack = 0.0;
5693 
5694  alpha = val * (lb - ub);
5695  assert(!SCIPisNegative(scip, alpha));
5696 
5697  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5698  {
5699  SCIP_Real newlb;
5700 
5701  /* compute new lower bound */
5702  newlb = ub + slack / val;
5703 
5704  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5705 
5706  if( *cutoff )
5707  {
5708  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5709  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5710 
5711  return SCIP_OKAY;
5712  }
5713  /* collect the new lower bound which is needed for the upper bound computation */
5714  lb = SCIPvarGetLbLocal(var);
5715  }
5716  }
5717 
5718  /* check, if we can tighten the variable's upper bound */
5719  if( !SCIPisInfinity(scip, -lhs) )
5720  {
5721  SCIP_Real slack;
5722  SCIP_Real alpha;
5723 
5724  /* make sure the max activity is reliable */
5725  if( !consdata->validmaxact )
5726  {
5727  consdataRecomputeMaxactivity(scip, consdata);
5728  }
5729  assert(consdata->validmaxact);
5730 
5731  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5732  if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5733  {
5734  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5735  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5736 
5737  *cutoff = TRUE;
5738  return SCIP_OKAY;
5739  }
5740 
5741  slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5742 
5743  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5744  * it to zero
5745  */
5746  if( !SCIPisPositive(scip, slack) )
5747  slack = 0.0;
5748 
5749  alpha = val * (lb - ub);
5750  assert(!SCIPisNegative(scip, alpha));
5751 
5752  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5753  {
5754  SCIP_Real newub;
5755 
5756  /* compute new upper bound */
5757  newub = lb - (slack / val);
5758 
5759  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5760 
5761  if( *cutoff )
5762  {
5763  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5764  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5765 
5766  return SCIP_OKAY;
5767  }
5768  }
5769  }
5770  }
5771 
5772  return SCIP_OKAY;
5773 }
5774 
5775 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5776 static
5778  SCIP* scip, /**< SCIP data structure */
5779  SCIP_CONS* cons, /**< conflict detecting constraint */
5780  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5781  int nvars, /**< number of variables reasoning the infeasibility */
5782  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5783  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5784  )
5785 {
5786 #ifndef NDEBUG
5787  SCIP_CONSDATA* consdata;
5788 
5789  assert(scip != NULL);
5790  assert(cons != NULL);
5791 
5792  consdata = SCIPconsGetData(cons);
5793  assert(consdata != NULL);
5794  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5795 #endif
5797  /* conflict analysis can only be applied in solving stage and if it is turned on */
5799  return SCIP_OKAY;
5800 
5801  /* initialize conflict analysis */
5803 
5804  /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5805  SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) );
5806 
5807  /* add reasoning variables to conflict candidate queue which led to the conflict */
5808  SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5809 
5810  /* analyze the conflict */
5811  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5812 
5813  return SCIP_OKAY;
5814 }
5815 
5816 /** propagate ranged rows
5817  *
5818  * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5819  * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5820  * variables better.
5821  *
5822  * Example:
5823  * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5824  *
5825  * x3 needs to be a multiple of 3, so the instance is infeasible.
5826  *
5827  * Example:
5828  * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5829  *
5830  * The only possible value for x3 is 2, so the variable will be fixed.
5831  *
5832  * @todo add holes if possible
5833  */
5834 static
5836  SCIP* scip, /**< SCIP data structure */
5837  SCIP_CONS* cons, /**< linear constraint */
5838  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5839  int* nfixedvars, /**< pointer to count number of fixed variables */
5840  int* nchgbds, /**< pointer to count the number of bound changes */
5841  int* naddconss /**< pointer to count number of added constraints */
5842  )
5843 {
5844  SCIP_CONSHDLRDATA* conshdlrdata;
5845  SCIP_CONSHDLR* conshdlr;
5846  SCIP_CONSDATA* consdata;
5847  SCIP_VAR** infcheckvars;
5848  SCIP_Real* infcheckvals;
5849  SCIP_Real minactinfvars;
5850  SCIP_Real maxactinfvars;
5851  SCIP_Real lb;
5852  SCIP_Real ub;
5853  SCIP_Real feastol;
5854  SCIP_Real fixedact;
5855  SCIP_Real lhs;
5856  SCIP_Real rhs;
5857  SCIP_Real absminbincoef;
5858  SCIP_Longint gcd;
5859  SCIP_Longint gcdtmp;
5860  SCIP_Bool minactinfvarsinvalid;
5861  SCIP_Bool maxactinfvarsinvalid;
5862  SCIP_Bool possiblegcd;
5863  SCIP_Bool gcdisone;
5864  SCIP_Bool addartconss;
5865  int ninfcheckvars;
5866  int nunfixedvars;
5867  int nfixedconsvars;
5868  int ncontvars;
5869  int pos;
5870  int v;
5871 
5872  assert(scip != NULL);
5873  assert(cons != NULL);
5874  assert(cutoff != NULL);
5875  assert(nfixedvars != NULL);
5876  assert(nchgbds != NULL);
5877  assert(naddconss != NULL);
5878 
5879  /* modifiable constraint can be changed so we do not have all necessary information */
5880  if( SCIPconsIsModifiable(cons) )
5881  return SCIP_OKAY;
5882 
5883  consdata = SCIPconsGetData(cons);
5884  assert(consdata != NULL);
5885 
5886  /* we already did full ranged row propagation */
5887  if( consdata->rangedrowpropagated == 2 )
5888  return SCIP_OKAY;
5889 
5890  /* at least three variables are needed */
5891  if( consdata->nvars < 3 )
5892  return SCIP_OKAY;
5893 
5894  /* do nothing on normal inequalities */
5895  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5896  return SCIP_OKAY;
5897 
5898  /* get constraint handler data */
5899  conshdlr = SCIPconsGetHdlr(cons);
5900  assert(conshdlr != NULL);
5901  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5902  assert(conshdlrdata != NULL);
5903 
5904  addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5905 
5906  /* we may add artificial constraints */
5907  if( addartconss )
5908  consdata->rangedrowpropagated = 2;
5909  /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5910  * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5911  * artificial constraints
5912  */
5913  else
5914  {
5915  if( consdata->rangedrowpropagated > 0 )
5916  return SCIP_OKAY;
5917 
5918  consdata->rangedrowpropagated = 1;
5919  }
5920  fixedact = 0;
5921  nfixedconsvars = 0;
5922  /* calculate fixed activity and number of fixed variables */
5923  for( v = consdata->nvars - 1; v >= 0; --v )
5924  {
5925  /* all zero coefficients should be eliminated */
5926  assert(!SCIPisZero(scip, consdata->vals[v]));
5927 
5928  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5929  {
5930  fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5931  ++nfixedconsvars;
5932  }
5933  }
5934 
5935  /* do not work with huge fixed activities */
5936  if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5937  return SCIP_OKAY;
5938 
5939  /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5940  assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5941  lhs = consdata->lhs - fixedact;
5942  rhs = consdata->rhs - fixedact;
5943  nunfixedvars = consdata->nvars - nfixedconsvars;
5944 
5945  /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5946  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5947  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5948 
5949  absminbincoef = SCIP_REAL_MAX;
5950  ncontvars = 0;
5951  gcdisone = TRUE;
5952  possiblegcd = TRUE;
5953 
5954  /* we now partition all unfixed variables in two groups:
5955  *
5956  * the first one contains all integral variable with integral
5957  * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5958  * given
5959  *
5960  * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5961  * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5962  */
5963 
5964  /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5965  * variables
5966  */
5967  ninfcheckvars = 0;
5968  v = -1;
5969  pos = -1;
5970  do
5971  {
5972  ++v;
5973 
5974  /* partition the variables, do not change the order of collection, because it might be used later on */
5975  while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5976  !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5977  {
5978  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5979  {
5980  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5981  {
5982  ++ncontvars;
5983  }
5984  else if( SCIPvarIsBinary(consdata->vars[v]) )
5985  {
5986  SCIP_Real absval;
5987 
5988  absval = REALABS(consdata->vals[v]);
5989 
5990  if( absminbincoef > absval )
5991  absminbincoef = absval;
5992  }
5993 
5994  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5995  possiblegcd = FALSE;
5996  infcheckvars[ninfcheckvars] = consdata->vars[v];
5997  infcheckvals[ninfcheckvars] = consdata->vals[v];
5998  ++ninfcheckvars;
5999 
6000  if( pos == -1 )
6001  pos = v;
6002  }
6003  ++v;
6004  }
6005  }
6006  while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
6007 
6008  /* if the first group of variables is empty, we stop */
6009  /* @todo try to propagate/split up a constraint of the form:
6010  * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
6011  * 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]
6012  */
6013  if( v == consdata->nvars )
6014  goto TERMINATE;
6015 
6016  /* we need at least two non-continuous variables */
6017  if( ncontvars + 2 > nunfixedvars )
6018  goto TERMINATE;
6019 
6020  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
6021  assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
6022 
6023  feastol = SCIPfeastol(scip);
6024 
6025  gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
6026  assert(gcd >= 2);
6027 
6028  /* go on to partition the variables, do not change the order of collection, because it might be used later on;
6029  * calculate gcd over the first part of variables */
6030  for( ; v < consdata->nvars; ++v )
6031  {
6032  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6033  continue;
6034 
6035  if( SCIPvarIsBinary(consdata->vars[v]) )
6036  {
6037  SCIP_Real absval;
6038 
6039  absval = REALABS(consdata->vals[v]);
6040 
6041  if( absminbincoef > absval )
6042  absminbincoef = absval;
6043  }
6044 
6045  if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
6046  SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
6047  {
6048  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
6049  ++ncontvars;
6050 
6051  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
6052  possiblegcd = FALSE;
6053  infcheckvars[ninfcheckvars] = consdata->vars[v];
6054  infcheckvals[ninfcheckvars] = consdata->vals[v];
6055 
6056  ++ninfcheckvars;
6057 
6058  if( pos == -1 )
6059  pos = v;
6060  }
6061  else
6062  {
6063  assert(REALABS(consdata->vals[v]) > 1.5);
6064 
6065  gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
6066  assert(gcdtmp >= 1);
6067 
6068  if( gcdtmp == 1 )
6069  {
6070  infcheckvars[ninfcheckvars] = consdata->vars[v];
6071  infcheckvals[ninfcheckvars] = consdata->vals[v];
6072 
6073  ++ninfcheckvars;
6074 
6075  if( pos == -1 )
6076  pos = v;
6077  }
6078  else
6079  gcd = gcdtmp;
6080  }
6081  }
6082  assert(gcd >= 2);
6083 
6084  /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
6085  * normalizeCons() */
6086  if( ninfcheckvars == 0 )
6087  goto TERMINATE;
6088 
6089  assert(pos >= 0);
6090 
6091  minactinfvarsinvalid = FALSE;
6092  maxactinfvarsinvalid = FALSE;
6093  maxactinfvars = 0.0;
6094  minactinfvars = 0.0;
6095 
6096  /* calculate activities over all infcheckvars */
6097  for( v = ninfcheckvars - 1; v >= 0; --v )
6098  {
6099  lb = SCIPvarGetLbLocal(infcheckvars[v]);
6100  ub = SCIPvarGetUbLocal(infcheckvars[v]);
6101 
6102  if( SCIPisInfinity(scip, -lb) )
6103  {
6104  if( infcheckvals[v] < 0.0 )
6105  maxactinfvarsinvalid = TRUE;
6106  else
6107  minactinfvarsinvalid = TRUE;
6108  }
6109  else
6110  {
6111  if( infcheckvals[v] < 0.0 )
6112  maxactinfvars += infcheckvals[v] * lb;
6113  else
6114  minactinfvars += infcheckvals[v] * lb;
6115  }
6116 
6117  if( SCIPisInfinity(scip, ub) )
6118  {
6119  if( infcheckvals[v] > 0.0 )
6120  maxactinfvarsinvalid = TRUE;
6121  else
6122  minactinfvarsinvalid = TRUE;
6123  }
6124  else
6125  {
6126  if( infcheckvals[v] > 0.0 )
6127  maxactinfvars += infcheckvals[v] * ub;
6128  else
6129  minactinfvars += infcheckvals[v] * ub;
6130  }
6131 
6132  /* better abort on to big values */
6133  if( SCIPisHugeValue(scip, -minactinfvars) )
6134  minactinfvarsinvalid = TRUE;
6135  if( SCIPisHugeValue(scip, maxactinfvars) )
6136  maxactinfvarsinvalid = TRUE;
6137 
6138  if( minactinfvarsinvalid || maxactinfvarsinvalid )
6139  goto TERMINATE;
6140  }
6141  assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6142 
6143  SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6144  minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6145 
6146  /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6147  /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6148  * activities */
6149  /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6150  * !!!note!!!
6151  * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6152  * are not at their global bound
6153  */
6154 
6155  /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6156  * infeasibility */
6157  if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6158  SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6159  {
6160  SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6161  SCIPdebugPrintCons(scip, cons, NULL);
6162 
6163  /* start conflict analysis */
6164  /* @todo improve conflict analysis by adding relaxed bounds */
6165  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6166 
6167  *cutoff = TRUE;
6168  }
6169  else if( ncontvars == 0 )
6170  {
6171  SCIP_Longint gcdinfvars = -1;
6172 
6173  /* check for gcd over all infcheckvars */
6174  if( possiblegcd )
6175  {
6176  v = ninfcheckvars - 1;
6177  gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6178  assert(gcdinfvars >= 2);
6179 
6180  for( ; v >= 0 && gcdinfvars >= 2; --v )
6181  {
6182  gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6183  }
6184  }
6185  else if( gcdisone )
6186  gcdinfvars = 1;
6187 
6188  SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6189 
6190  /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6191  if( gcdinfvars >= 1 )
6192  {
6193  SCIP_Real value;
6194  SCIP_Real value2;
6195  SCIP_Real minvalue = SCIP_INVALID;
6196  SCIP_Real maxvalue = SCIP_INVALID;
6197  int nsols = 0;
6198 
6199  value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6200 
6201  /* check how many possible solutions exist */
6202  while( SCIPisLE(scip, value, maxactinfvars) )
6203  {
6204  value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6205 
6206  /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6207  if( !SCIPisGE(scip, value2, lhs) )
6208  {
6209  value2 += gcd;
6210  }
6211 
6212  if( SCIPisLE(scip, value2, rhs) )
6213  {
6214  ++nsols;
6215 
6216  /* early termination if we found more than two solutions */
6217  if( nsols == 3 )
6218  break;
6219 
6220  if( minvalue == SCIP_INVALID ) /*lint !e777*/
6221  minvalue = value;
6222 
6223  maxvalue = value;
6224  }
6225  value += gcdinfvars;
6226  }
6227  assert(nsols < 2 || minvalue <= maxvalue);
6228 
6229  /* determine last possible solution for better bounding */
6230  if( nsols == 3 )
6231  {
6232 #ifndef NDEBUG
6233  SCIP_Real secondsolval = maxvalue;
6234 #endif
6235  value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6236 
6237  /* check how many possible solutions exist */
6238  while( SCIPisGE(scip, value, minactinfvars) )
6239  {
6240  value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6241 
6242  /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6243  if( !SCIPisLE(scip, value2, rhs) )
6244  {
6245  value2 -= gcd;
6246  }
6247 
6248  if( SCIPisGE(scip, value2, lhs) )
6249  {
6250  maxvalue = value;
6251  assert(maxvalue > minvalue);
6252  break;
6253  }
6254  value -= gcdinfvars;
6255  }
6256  assert(maxvalue > secondsolval);
6257  }
6258 
6259  SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6260  nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6261 
6262  /* no possible solution found */
6263  if( nsols == 0 )
6264  {
6265  SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6266  gcdinfvars, gcd, lhs, rhs);
6267  SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6268  SCIPdebugPrintCons(scip, cons, NULL);
6269 
6270  /* start conflict analysis */
6271  /* @todo improve conflict analysis by adding relaxed bounds */
6272  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6273 
6274  *cutoff = TRUE;
6275  }
6276  /* if only one solution exist we can extract a new constraint or fix variables */
6277  else if( nsols == 1 )
6278  {
6279  assert(minvalue == maxvalue); /*lint !e777*/
6280 
6281  /* we can fix the only variable in our second set of variables */
6282  if( ninfcheckvars == 1 )
6283  {
6284  SCIP_Bool fixed;
6285 
6286  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6287 
6288  SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6289  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6290  SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6291 
6292  /* fix variable to only possible value */
6293  SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6294  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6295 
6296  if( *cutoff )
6297  {
6298  /* start conflict analysis */
6299  /* @todo improve conflict analysis by adding relaxed bounds */
6300  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6301  }
6302 
6303  if( fixed )
6304  ++(*nfixedvars);
6305  }
6306  else
6307  {
6308  /* check for exactly one unfixed variable which is not part of the infcheckvars */
6309  if( ninfcheckvars == nunfixedvars - 1 )
6310  {
6311  SCIP_Real bound;
6312  SCIP_Bool foundvar = FALSE;
6313  SCIP_Bool fixed;
6314  int w = 0;
6315 
6316  assert(ninfcheckvars > 0);
6317 
6318  /* find variable which is not an infcheckvar and fix it */
6319  for( v = 0; v < consdata->nvars - 1; ++v )
6320  {
6321  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6322  {
6323  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6324  {
6325 #ifndef NDEBUG
6326  int v2 = v + 1;
6327  int w2 = w;
6328 
6329  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6330 
6331  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6332  {
6333  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6334  continue;
6335 
6336  assert(consdata->vars[v2] == infcheckvars[w2]);
6337  ++w2;
6338  }
6339  assert(w2 == ninfcheckvars);
6340 #endif
6341  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6342 
6343  foundvar = TRUE;
6344 
6345  if( consdata->vals[v] < 0 )
6346  {
6347  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6348  }
6349  else
6350  {
6351  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6352  }
6353 
6354  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6355  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6356  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6357 
6358  /* fix variable to only possible value */
6359  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6360  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6361 
6362  if( *cutoff )
6363  {
6364  /* start conflict analysis */
6365  /* @todo improve conflict analysis by adding relaxed bounds */
6366  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6367  consdata->vars[v], bound) );
6368  }
6369 
6370  if( fixed )
6371  ++(*nfixedvars);
6372 
6373  break;
6374  }
6375 
6376  ++w;
6377  }
6378  }
6379 
6380  /* maybe last variable was the not infcheckvar */
6381  if( !foundvar )
6382  {
6383  assert(v == consdata->nvars - 1);
6384  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6385 
6386  if( consdata->vals[v] < 0 )
6387  {
6388  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6389  }
6390  else
6391  {
6392  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6393  }
6394 
6395  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6396  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6397  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6398 
6399  /* fix variable to only possible value */
6400  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6401  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6402 
6403  if( *cutoff )
6404  {
6405  /* start conflict analysis */
6406  /* @todo improve conflict analysis by adding relaxed bounds */
6407  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6408  consdata->vars[v], bound) );
6409  }
6410 
6411  if( fixed )
6412  ++(*nfixedvars);
6413  }
6414  }
6415  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6416  {
6417  /* aggregation possible if we have two variables, but this will be done later on */
6418  SCIP_CONS* newcons;
6419  char name[SCIP_MAXSTRLEN];
6420 
6421  /* create, add, and release new artificial constraint */
6422  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6423  ++conshdlrdata->naddconss;
6424 
6425  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6426 
6427  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6428  maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6429  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6430 
6431  SCIPdebugPrintCons(scip, newcons, NULL);
6432 
6433  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6434 
6435  ++(*naddconss);
6436  }
6437  }
6438  }
6439  /* at least two solutions */
6440  else
6441  {
6442  /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6443 
6444  /* only one variable in the second set, so we can bound this variables */
6445  if( ninfcheckvars == 1 )
6446  {
6447  SCIP_Bool tightened;
6448  SCIP_Real newlb;
6449  SCIP_Real newub;
6450 
6451  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6452 
6453  if( infcheckvals[0] < 0 )
6454  {
6455  newlb = maxvalue/infcheckvals[0];
6456  newub = minvalue/infcheckvals[0];
6457  }
6458  else
6459  {
6460  newlb = minvalue/infcheckvals[0];
6461  newub = maxvalue/infcheckvals[0];
6462  }
6463  assert(newlb < newub);
6464 
6465  if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6466  {
6467  /* update lower bound of variable */
6468  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6469  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6470 
6471  /* tighten variable lower bound to minimal possible value */
6472  SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6473  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6474 
6475  if( *cutoff )
6476  {
6477  /* start conflict analysis */
6478  /* @todo improve conflict analysis by adding relaxed bounds */
6479  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6480  }
6481 
6482  if( tightened )
6483  ++(*nchgbds);
6484  }
6485 
6486  if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6487  {
6488  /* update upper bound of variable */
6489  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6490  SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6491 
6492  /* tighten variable upper bound to maximal possible value */
6493  SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6494  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6495 
6496  if( *cutoff )
6497  {
6498  /* start conflict analysis */
6499  /* @todo improve conflict analysis by adding relaxed bounds */
6500  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6501  }
6502 
6503  if( tightened )
6504  ++(*nchgbds);
6505  }
6506  }
6507  /* check if we have only one not infcheckvars, if so we can tighten this variable */
6508  else if( ninfcheckvars == nunfixedvars - 1 )
6509  {
6510  SCIP_Bool foundvar = FALSE;
6511  SCIP_Bool tightened;
6512  SCIP_Real newlb;
6513  SCIP_Real newub;
6514  int w = 0;
6515 
6516  assert(ninfcheckvars > 0);
6517  assert(minvalue < maxvalue);
6518 
6519  /* find variable which is not an infcheckvar and fix it */
6520  for( v = 0; v < consdata->nvars - 1; ++v )
6521  {
6522  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6523  {
6524  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6525  {
6526 #ifndef NDEBUG
6527  int v2 = v + 1;
6528  int w2 = w;
6529 
6530  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6531 
6532  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6533  {
6534  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6535  continue;
6536 
6537  assert(consdata->vars[v2] == infcheckvars[w2]);
6538  ++w2;
6539  }
6540  assert(w2 == ninfcheckvars);
6541 #endif
6542 
6543  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6544  foundvar = TRUE;
6545 
6546  if( consdata->vals[v] < 0 )
6547  {
6548  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6549  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6550  }
6551  else
6552  {
6553  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6554  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6555  }
6556  assert(SCIPisLE(scip, newlb, newub));
6557 
6558  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6559  {
6560  /* update lower bound of variable */
6561  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6562  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6563 
6564  /* tighten variable lower bound to minimal possible value */
6565  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6566  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6567 
6568  if( *cutoff )
6569  {
6570  /* start conflict analysis */
6571  /* @todo improve conflict analysis by adding relaxed bounds */
6572  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6573  consdata->vars[v], newlb) );
6574  }
6575 
6576  if( tightened )
6577  ++(*nchgbds);
6578  }
6579 
6580  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6581  {
6582  /* update upper bound of variable */
6583  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6584  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6585 
6586  /* tighten variable upper bound to maximal possible value */
6587  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6588  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6589 
6590  if( *cutoff )
6591  {
6592  /* start conflict analysis */
6593  /* @todo improve conflict analysis by adding relaxed bounds */
6594  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6595  consdata->vars[v], newub) );
6596  }
6597 
6598  if( tightened )
6599  ++(*nchgbds);
6600  }
6601 
6602  break;
6603  }
6604 
6605  ++w;
6606  }
6607  }
6608 
6609  /* maybe last variable was the not infcheckvar */
6610  if( !foundvar )
6611  {
6612  assert(v == consdata->nvars - 1);
6613  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6614 
6615  if( consdata->vals[v] < 0 )
6616  {
6617  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6618  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6619  }
6620  else
6621  {
6622  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6623  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6624  }
6625  assert(SCIPisLE(scip, newlb, newub));
6626 
6627  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6628  {
6629  /* update lower bound of variable */
6630  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6631  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6632 
6633  /* tighten variable lower bound to minimal possible value */
6634  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6635  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6636 
6637  if( *cutoff )
6638  {
6639  /* start conflict analysis */
6640  /* @todo improve conflict analysis by adding relaxed bounds */
6641  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6642  }
6643 
6644  if( tightened )
6645  ++(*nchgbds);
6646  }
6647 
6648  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6649  {
6650  /* update upper bound of variable */
6651  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6652  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6653 
6654  /* tighten variable upper bound to maximal possible value */
6655  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6656  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6657 
6658  if( *cutoff )
6659  {
6660  /* start conflict analysis */
6661  /* @todo improve conflict analysis by adding relaxed bounds */
6662  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6663  }
6664 
6665  if( tightened )
6666  ++(*nchgbds);
6667  }
6668  }
6669  }
6670  /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6671  * region for our infcheckvars, if possible
6672  */
6673  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6674  {
6675  SCIP_CONS* newcons;
6676  char name[SCIP_MAXSTRLEN];
6677  SCIP_Real newlhs;
6678  SCIP_Real newrhs;
6679 
6680  assert(maxvalue > minvalue);
6681 
6682  if( SCIPisGT(scip, minvalue, minactinfvars) )
6683  newlhs = minvalue;
6684  else
6685  newlhs = -SCIPinfinity(scip);
6686 
6687  if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6688  newrhs = maxvalue;
6689  else
6690  newrhs = SCIPinfinity(scip);
6691 
6692  if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6693  {
6694  /* create, add, and release new artificial constraint */
6695  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6696  ++conshdlrdata->naddconss;
6697 
6698  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6699 
6700  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6701  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6702  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6703 
6704  SCIPdebugPrintCons(scip, newcons, NULL);
6705  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6706 
6707  ++(*naddconss);
6708  }
6709  /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6710  * should be maxvalue */
6711  }
6712  }
6713  }
6714  }
6715  else if( addartconss && ncontvars < ninfcheckvars )
6716  {
6717  SCIP_Real maxact = 0.0;
6718  SCIP_Real minact = 0.0;
6719  int w = 0;
6720 
6721  /* compute activities of non-infcheckvars */
6722  for( v = 0; v < consdata->nvars; ++v )
6723  {
6724  if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6725  {
6726  ++w;
6727  continue;
6728  }
6729 
6730  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6731  {
6732  if( SCIPvarIsBinary(consdata->vars[v]) )
6733  {
6734  if( consdata->vals[v] > 0.0 )
6735  maxact += consdata->vals[v];
6736  else
6737  minact += consdata->vals[v];
6738  }
6739  else
6740  {
6741  SCIP_Real tmpval;
6742 
6743  assert(SCIPvarIsIntegral(consdata->vars[v]));
6744 
6745  if( consdata->vals[v] > 0.0 )
6746  {
6747  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6748 
6749  if( SCIPisHugeValue(scip, -tmpval) )
6750  break;
6751 
6752  minact += tmpval;
6753 
6754  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6755 
6756  if( SCIPisHugeValue(scip, tmpval) )
6757  break;
6758 
6759  maxact += tmpval;
6760  }
6761  else
6762  {
6763  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6764 
6765  if( SCIPisHugeValue(scip, -tmpval) )
6766  break;
6767 
6768  minact += tmpval;
6769 
6770  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6771 
6772  if( SCIPisHugeValue(scip, tmpval) )
6773  break;
6774 
6775  maxact += tmpval;
6776  }
6777  }
6778  }
6779  }
6780  if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6781  {
6782  SCIP_CONS* newcons;
6783  char name[SCIP_MAXSTRLEN];
6784  SCIP_Real newlhs;
6785  SCIP_Real newrhs;
6786 
6787  assert(maxact > minact);
6788  assert(w == ninfcheckvars);
6789 
6790  newlhs = lhs - maxact;
6791  newrhs = rhs - minact;
6792  assert(newlhs < newrhs);
6793 
6794  /* create, add, and release new artificial constraint */
6795  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6796  ++conshdlrdata->naddconss;
6797 
6798  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6799 
6800  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6801  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6802  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6803 
6804  SCIPdebugPrintCons(scip, newcons, NULL);
6805  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6806 
6807  ++(*naddconss);
6808  }
6809  }
6810 
6811  TERMINATE:
6812  SCIPfreeBufferArray(scip, &infcheckvals);
6813  SCIPfreeBufferArray(scip, &infcheckvars);
6814 
6815  return SCIP_OKAY;
6816 }
6817 
6818 /** tightens bounds of a single variable due to activity bounds */
6819 static
6821  SCIP* scip, /**< SCIP data structure */
6822  SCIP_CONS* cons, /**< linear constraint */
6823  int pos, /**< position of the variable in the vars array */
6824  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6825  int* nchgbds, /**< pointer to count the total number of tightened bounds */
6826  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6827  )
6828 {
6829  SCIP_CONSDATA* consdata;
6830  SCIP_VAR* var;
6831  SCIP_Real val;
6832  SCIP_Real lb;
6833  SCIP_Real ub;
6834  SCIP_Real minresactivity;
6835  SCIP_Real maxresactivity;
6836  SCIP_Real lhs;
6837  SCIP_Real rhs;
6838  SCIP_Bool infeasible;
6839  SCIP_Bool tightened;
6840  SCIP_Bool ismintight;
6841  SCIP_Bool ismaxtight;
6842  SCIP_Bool isminsettoinfinity;
6843  SCIP_Bool ismaxsettoinfinity;
6844 
6845  assert(scip != NULL);
6846  assert(cons != NULL);
6847  assert(cutoff != NULL);
6848  assert(nchgbds != NULL);
6849 
6850  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6851  if( SCIPconsIsModifiable(cons) )
6852  return SCIP_OKAY;
6853 
6854  consdata = SCIPconsGetData(cons);
6855  assert(consdata != NULL);
6856  assert(0 <= pos && pos < consdata->nvars);
6857 
6858  *cutoff = FALSE;
6859 
6860  var = consdata->vars[pos];
6861 
6862  /* we cannot tighten bounds of multi-aggregated variables */
6864  return SCIP_OKAY;
6865 
6866  val = consdata->vals[pos];
6867  lhs = consdata->lhs;
6868  rhs = consdata->rhs;
6869  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6870  &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
6871  assert(var != NULL);
6872  assert(!SCIPisZero(scip, val));
6873  assert(!SCIPisInfinity(scip, lhs));
6874  assert(!SCIPisInfinity(scip, -rhs));
6875 
6876  lb = SCIPvarGetLbLocal(var);
6877  ub = SCIPvarGetUbLocal(var);
6878  assert(SCIPisLE(scip, lb, ub));
6879 
6880  if( val > 0.0 )
6881  {
6882  /* check, if we can tighten the variable's bounds */
6883  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight )
6884  {
6885  SCIP_Real newub;
6886 
6887  newub = (rhs - minresactivity)/val;
6888 
6889  if( !SCIPisInfinity(scip, newub) &&
6890  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6891  {
6892  SCIP_Bool activityunreliable;
6893  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6894 
6895  /* check minresactivities for reliability */
6896  if( activityunreliable )
6897  {
6898  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6899  newub = (rhs - minresactivity)/val;
6900  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6901  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6902  && (!force || !SCIPisLT(scip, newub, ub)));
6903  }
6904 
6905  if( !activityunreliable )
6906  {
6907  /* tighten upper bound */
6908  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6909  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6910  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6911  &infeasible, &tightened) );
6912  if( infeasible )
6913  {
6914  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6915  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6916 
6917  /* analyze conflict */
6918  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6919 
6920  *cutoff = TRUE;
6921  return SCIP_OKAY;
6922  }
6923  if( tightened )
6924  {
6925  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6926  assert(SCIPisFeasLE(scip, ub, newub));
6927  (*nchgbds)++;
6928 
6929  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6930  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6931  }
6932  }
6933  }
6934  }
6935 
6936  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight )
6937  {
6938  SCIP_Real newlb;
6939 
6940  newlb = (lhs - maxresactivity)/val;
6941  if( !SCIPisInfinity(scip, -newlb) &&
6942  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6943  {
6944  /* check maxresactivities for reliability */
6945  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6946  {
6947  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6948  newlb = (lhs - maxresactivity)/val;
6949 
6950  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6951  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6952  && (!force || !SCIPisGT(scip, newlb, lb))) )
6953  return SCIP_OKAY;
6954  }
6955 
6956  /* tighten lower bound */
6957  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6958  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6959  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6960  &infeasible, &tightened) );
6961  if( infeasible )
6962  {
6963  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6964  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6965 
6966  /* analyze conflict */
6967  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6968 
6969  *cutoff = TRUE;
6970  return SCIP_OKAY;
6971  }
6972  if( tightened )
6973  {
6974  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6975  assert(SCIPisFeasGE(scip, lb, newlb));
6976  (*nchgbds)++;
6977  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6978  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6979  }
6980  }
6981  }
6982  }
6983  else
6984  {
6985  /* check, if we can tighten the variable's bounds */
6986  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight )
6987  {
6988  SCIP_Real newlb;
6989 
6990  newlb = (rhs - minresactivity)/val;
6991  if( !SCIPisInfinity(scip, -newlb) &&
6992  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6993  {
6994  SCIP_Bool activityunreliable;
6995  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6996  /* check minresactivities for reliability */
6997  if( activityunreliable )
6998  {
6999  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
7000  newlb = (rhs - minresactivity)/val;
7001 
7002  activityunreliable = SCIPisInfinity(scip, -minresactivity)
7003  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
7004  && (!force || !SCIPisGT(scip, newlb, lb)));
7005  }
7006 
7007  if( !activityunreliable )
7008  {
7009  /* tighten lower bound */
7010  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
7011  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
7012  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
7013  &infeasible, &tightened) );
7014  if( infeasible )
7015  {
7016  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7017  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
7018 
7019  /* analyze conflict */
7020  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7021 
7022  *cutoff = TRUE;
7023  return SCIP_OKAY;
7024  }
7025  if( tightened )
7026  {
7027  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7028  assert(SCIPisFeasGE(scip, lb, newlb));
7029  (*nchgbds)++;
7030  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7031  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7032  }
7033  }
7034  }
7035  }
7036 
7037  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight )
7038  {
7039  SCIP_Real newub;
7040 
7041  newub = (lhs - maxresactivity)/val;
7042  if( !SCIPisInfinity(scip, newub) &&
7043  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
7044  {
7045  /* check maxresactivities for reliability */
7046  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
7047  {
7048  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
7049  newub = (lhs - maxresactivity)/val;
7050 
7051  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
7052  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
7053  && (!force || !SCIPisLT(scip, newub, ub))) )
7054  return SCIP_OKAY;
7055  }
7056 
7057  /* tighten upper bound */
7058  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
7059  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
7060  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
7061  &infeasible, &tightened) );
7062  if( infeasible )
7063  {
7064  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7065  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
7066 
7067  /* analyze conflict */
7068  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7069 
7070  *cutoff = TRUE;
7071  return SCIP_OKAY;
7072  }
7073  if( tightened )
7074  {
7075  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7076  assert(SCIPisFeasLE(scip, ub, newub));
7077  (*nchgbds)++;
7078  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7079  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7080  }
7081  }
7082  }
7083  }
7084 
7085  return SCIP_OKAY;
7086 }
7087 
7088 #define MAXTIGHTENROUNDS 10
7089 
7090 /** tightens bounds of variables in constraint due to activity bounds */
7091 static
7093  SCIP* scip, /**< SCIP data structure */
7094  SCIP_CONS* cons, /**< linear constraint */
7095  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7096  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7097  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7098  int* nchgbds /**< pointer to count the total number of tightened bounds */
7099  )
7100 {
7101  SCIP_CONSDATA* consdata;
7102  unsigned int tightenmode;
7103  int nvars;
7104  int nrounds;
7105  int lastchange;
7106  int oldnchgbds;
7107 #ifndef SCIP_DEBUG
7108  int oldnchgbdstotal;
7109 #endif
7110  int v;
7111  SCIP_Bool force;
7112  SCIP_Bool easycase;
7113 
7114  assert(scip != NULL);
7115  assert(cons != NULL);
7116  assert(nchgbds != NULL);
7117  assert(cutoff != NULL);
7118 
7119  *cutoff = FALSE;
7120 
7121  /* we cannot tighten variables' bounds, if the constraint may be not complete */
7122  if( SCIPconsIsModifiable(cons) )
7123  return SCIP_OKAY;
7124 
7125  /* if a constraint was created after presolve, then it may hold fixed variables
7126  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7127  * thus, ensure here again that variable fixings have been applied
7128  */
7129  SCIP_CALL( applyFixings(scip, cons, cutoff) );
7130  if( *cutoff )
7131  return SCIP_OKAY;
7132 
7133  /* check if constraint has any chances of tightening bounds */
7134  if( !canTightenBounds(cons) )
7135  return SCIP_OKAY;
7136 
7137  consdata = SCIPconsGetData(cons);
7138  assert(consdata != NULL);
7139 
7140  nvars = consdata->nvars;
7141  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7142 
7143  /* we are at the root node or during presolving */
7144  if( SCIPgetDepth(scip) < 1 )
7145  tightenmode = 2;
7146  else
7147  tightenmode = 1;
7148 
7149  /* stop if we already tightened the constraint and the tightening is not forced */
7150  if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7151  return SCIP_OKAY;
7152 
7153  /* ensure that the variables are properly sorted */
7154  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7155  {
7156  SCIP_CALL( consdataSort(scip, consdata) );
7157  assert(consdata->coefsorted);
7158  }
7159 
7160  /* update maximal activity delta if necessary */
7161  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7162  consdataRecomputeMaxActivityDelta(scip, consdata);
7163 
7164  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7165  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7166  checkMaxActivityDelta(scip, consdata);
7167 
7168  /* this may happen if all variables are fixed */
7169  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7170  return SCIP_OKAY;
7171 
7172  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7173  {
7174  SCIP_Real slack;
7175  SCIP_Real surplus;
7176  SCIP_Real minactivity;
7177  SCIP_Real maxactivity;
7178  SCIP_Bool ismintight;
7179  SCIP_Bool ismaxtight;
7180  SCIP_Bool isminsettoinfinity;
7181  SCIP_Bool ismaxsettoinfinity;
7182 
7183  /* use maximal activity delta to skip propagation (cannot deduce anything) */
7184  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &ismintight, &ismaxtight,
7185  &isminsettoinfinity, &ismaxsettoinfinity);
7186  assert(!SCIPisInfinity(scip, minactivity));
7187  assert(!SCIPisInfinity(scip, -maxactivity));
7188 
7189  slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7190  surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7191 
7192  /* check if the constraint will propagate */
7193  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7194  return SCIP_OKAY;
7195  }
7196 
7197  /* check if we can use fast implementation for easy and numerically well behaved cases */
7198  easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7199 
7200  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7201  lastchange = -1;
7202  oldnchgbds = 0;
7203 
7204 #ifndef SCIP_DEBUG
7205  oldnchgbdstotal = *nchgbds;
7206 #endif
7207 
7208  for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7209  {
7210  /* ensure that the variables are properly sorted
7211  *
7212  * note: it might happen that integer variables become binary during bound tightening at the root node
7213  */
7214  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7215  {
7216  SCIP_CALL( consdataSort(scip, consdata) );
7217  assert(consdata->coefsorted);
7218  }
7219 
7220  /* mark the constraint to have the variables' bounds tightened */
7221  consdata->boundstightened = (unsigned int)tightenmode;
7222 
7223  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7224  * sorting enables skipping variables
7225  */
7226  v = 0;
7227  while( v < nvars && v != lastchange && !(*cutoff) )
7228  {
7229  oldnchgbds = *nchgbds;
7230 
7231  if( easycase )
7232  {
7233  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7234  }
7235  else
7236  {
7237  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7238  }
7239 
7240  /* if there was no progress, skip the rest of the binary variables */
7241  if( *nchgbds > oldnchgbds )
7242  {
7243  lastchange = v;
7244  ++v;
7245  }
7246  else if( consdata->coefsorted && v < consdata->nbinvars - 1
7247  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7248  v = consdata->nbinvars;
7249  else
7250  ++v;
7251  }
7252 
7253 #ifndef SCIP_DEBUG
7254  SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7255  *nchgbds - oldnchgbdstotal, nrounds);
7256  oldnchgbdstotal += oldnchgbds;
7257 #endif
7258  }
7259 
7260 #ifndef NDEBUG
7261  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7262  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7263 #endif
7264 
7265  return SCIP_OKAY;
7266 }
7267 
7268 /** checks linear constraint for feasibility of given solution or current solution */
7269 static
7271  SCIP* scip, /**< SCIP data structure */
7272  SCIP_CONS* cons, /**< linear constraint */
7273  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7274  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7275  SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7276  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7277  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7278  )
7279 {
7280  SCIP_CONSDATA* consdata;
7281  SCIP_Real activity;
7282  SCIP_Real absviol;
7283  SCIP_Real relviol;
7284  SCIP_Real lhsviol;
7285  SCIP_Real rhsviol;
7286 
7287  assert(scip != NULL);
7288  assert(cons != NULL);
7289  assert(violated != NULL);
7290 
7291  SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7292  SCIPdebugPrintCons(scip, cons, NULL);
7293 
7294  consdata = SCIPconsGetData(cons);
7295  assert(consdata != NULL);
7296 
7297  *violated = FALSE;
7298 
7299  if( consdata->row != NULL )
7300  {
7301  if( !checklprows && SCIProwIsInLP(consdata->row) )
7302  return SCIP_OKAY;
7303  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7304  activity = consdataComputePseudoActivity(scip, consdata);
7305  else
7306  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7307  }
7308  else
7309  activity = consdataGetActivity(scip, consdata, sol);
7310 
7311  SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7312  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7313  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7314  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7315 
7316  /* calculate absolute and relative bound violations */
7317  lhsviol = consdata->lhs - activity;
7318  rhsviol = activity - consdata->rhs;
7319 
7320  absviol = 0.0;
7321  relviol = 0.0;
7322  if( (lhsviol > 0) && (lhsviol > rhsviol) )
7323  {
7324  absviol = lhsviol;
7325  relviol = SCIPrelDiff(consdata->lhs, activity);
7326  }
7327  else if( rhsviol > 0 )
7328  {
7329  absviol = rhsviol;
7330  relviol = SCIPrelDiff(activity, consdata->rhs);
7331  }
7332 
7333  /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7334  * return infeasible for safety
7335  */
7336  if( activity == SCIP_INVALID ) /*lint !e777*/
7337  {
7338  assert(sol == NULL);
7339  *violated = TRUE;
7340 
7341  /* set violation of invalid pseudo solutions */
7342  absviol = SCIP_INVALID;
7343  relviol = SCIP_INVALID;
7344 
7345  /* reset constraint age since we are in enforcement */
7346  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7347  }
7348  /* check with relative tolerances (the default) */
7349  else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7350  {
7351  /* the "normal" check: one of the two sides is violated */
7352  if( !checkrelmaxabs )
7353  {
7354  *violated = TRUE;
7355 
7356  /* only reset constraint age if we are in enforcement */
7357  if( sol == NULL )
7358  {
7359  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7360  }
7361  }
7362  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7363  * small compared to the absolute values occurring in the activity
7364  */
7365  else
7366  {
7367  SCIP_Real maxabs;
7368  SCIP_Real coef;
7369  SCIP_Real absval;
7370  SCIP_Real solval;
7371  int v;
7372 
7373  maxabs = 1.0;
7374 
7375  /* compute maximum absolute value */
7376  for( v = 0; v < consdata->nvars; ++v )
7377  {
7378  if( consdata->vals != NULL )
7379  {
7380  coef = consdata->vals[v];
7381  }
7382  else
7383  coef = 1.0;
7384 
7385  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7386  absval = REALABS( coef * solval );
7387  maxabs = MAX( maxabs, absval );
7388  }
7389 
7390  /* regard left hand side, first */
7391  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7392  {
7393  /* check whether violation is random noise */
7394  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7395  {
7396  SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7397  consdata->lhs - activity, maxabs);
7398  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7399 
7400  /* only increase constraint age if we are in enforcement */
7401  if( sol == NULL )
7402  {
7403  SCIP_CALL( SCIPincConsAge(scip, cons) );
7404  }
7405  }
7406  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7407  else if( SCIPisZero(scip, consdata->lhs) )
7408  {
7409  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7410  {
7411  SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7412  consdata->lhs - activity, maxabs);
7413  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7414 
7415  /* only increase constraint age if we are in enforcement */
7416  if( sol == NULL )
7417  {
7418  SCIP_CALL( SCIPincConsAge(scip, cons) );
7419  }
7420  }
7421  else
7422  {
7423  *violated = TRUE;
7424 
7425  /* only reset constraint age if we are in enforcement */
7426  if( sol == NULL )
7427  {
7428  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7429  }
7430  }
7431  }
7432  else
7433  {
7434  *violated = TRUE;
7435 
7436  /* only reset constraint age if we are in enforcement */
7437  if( sol == NULL )
7438  {
7439  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7440  }
7441  }
7442  }
7443 
7444  /* now regard right hand side */
7445  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7446  {
7447  /* check whether violation is random noise */
7448  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7449  {
7450  SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7451  activity - consdata->rhs, maxabs);
7452  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7453 
7454  /* only increase constraint age if we are in enforcement */
7455  if( sol == NULL )
7456  {
7457  SCIP_CALL( SCIPincConsAge(scip, cons) );
7458  }
7459  }
7460  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7461  else if( SCIPisZero(scip, consdata->rhs) )
7462  {
7463  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7464  {
7465  SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7466  activity - consdata->rhs, maxabs);
7467  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7468 
7469  /* only increase constraint age if we are in enforcement */
7470  if( sol == NULL )
7471  {
7472  SCIP_CALL( SCIPincConsAge(scip, cons) );
7473  }
7474  }
7475  else
7476  {
7477  *violated = TRUE;
7478 
7479  /* only reset constraint age if we are in enforcement */
7480  if( sol == NULL )
7481  {
7482  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7483  }
7484  }
7485  }
7486  else
7487  {
7488  *violated = TRUE;
7489 
7490  /* only reset constraint age if we are in enforcement */
7491  if( sol == NULL )
7492  {
7493  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7494  }
7495  }
7496  }
7497  }
7498  }
7499  /* check with absolute tolerances */
7500  else if( consdata->checkabsolute &&
7501  ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7502  (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7503  {
7504  *violated = TRUE;
7505 
7506  /* only reset constraint age if we are in enforcement */
7507  if( sol == NULL )
7508  {
7509  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7510  }
7511  }
7512  else
7513  {
7514  /* only increase constraint age if we are in enforcement */
7515  if( sol == NULL )
7516  {
7517  SCIP_CALL( SCIPincConsAge(scip, cons) );
7518  }
7519  }
7520 
7521  /* update absolute and relative violation of the solution */
7522  if( sol != NULL )
7523  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7524 
7525  return SCIP_OKAY;
7526 }
7527 
7528 /** creates an LP row in a linear constraint data */
7529 static
7531  SCIP* scip, /**< SCIP data structure */
7532  SCIP_CONS* cons /**< linear constraint */
7533  )
7534 {
7535  SCIP_CONSDATA* consdata;
7536 
7537  assert(scip != NULL);
7538  assert(cons != NULL);
7539 
7540  consdata = SCIPconsGetData(cons);
7541  assert(consdata != NULL);
7542  assert(consdata->row == NULL);
7543 
7544  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7546 
7547  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7548 
7549  return SCIP_OKAY;
7550 }
7551 
7552 /** adds linear constraint as cut to the LP */
7553 static
7555  SCIP* scip, /**< SCIP data structure */
7556  SCIP_CONS* cons, /**< linear constraint */
7557  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7558  )
7559 {
7560  SCIP_CONSDATA* consdata;
7561 
7562  assert(scip != NULL);
7563  assert(cons != NULL);
7564 
7565  consdata = SCIPconsGetData(cons);
7566  assert(consdata != NULL);
7567 
7568  if( consdata->row == NULL )
7569  {
7570  if( !SCIPconsIsModifiable(cons) )
7571  {
7572  /* 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
7573  * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7574  */
7575  SCIP_CALL( applyFixings(scip, cons, cutoff) );
7576  if( *cutoff )
7577  return SCIP_OKAY;
7578  }
7579 
7580  /* convert consdata object into LP row */
7581  SCIP_CALL( createRow(scip, cons) );
7582  }
7583  assert(consdata->row != NULL);
7584 
7585  if( consdata->nvars == 0 )
7586  {
7587  SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7588  }
7589 
7590  /* insert LP row as cut */
7591  if( !SCIProwIsInLP(consdata->row) )
7592  {
7593  SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7594  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7595  /* if presolving is turned off, the row might be trivial */
7596  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7597  {
7598  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7599  }
7600 #ifndef NDEBUG
7601  else
7602  {
7603  int pr;
7604  int cr;
7605  SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7606  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7607  assert( pr == 0 || cr == 0 );
7608  }
7609 #endif
7610  }
7611 
7612  return SCIP_OKAY;
7613 }
7614 
7615 /** adds linear constraint as row to the NLP, if not added yet */
7616 static
7618  SCIP* scip, /**< SCIP data structure */
7619  SCIP_CONS* cons /**< linear constraint */
7620  )
7621 {
7622  SCIP_CONSDATA* consdata;
7623 
7624  assert(SCIPisNLPConstructed(scip));
7625 
7626  /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7627  if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7628  return SCIP_OKAY;
7629 
7630  consdata = SCIPconsGetData(cons);
7631  assert(consdata != NULL);
7632 
7633  if( consdata->nlrow == NULL )
7634  {
7635  assert(consdata->lhs <= consdata->rhs);
7637  SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7638  0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7639 
7640  assert(consdata->nlrow != NULL);
7641  }
7642 
7643  if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7644  {
7645  SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7646  }
7647 
7648  return SCIP_OKAY;
7649 }
7650 
7651 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7652 static
7654  SCIP* scip, /**< SCIP data structure */
7655  SCIP_CONS* cons, /**< linear constraint */
7656  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7657  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7658  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7659  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7660  * the ones with non-zero dual value? */
7661  int* ncuts, /**< pointer to add up the number of found cuts */
7662  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7663  )
7664 {
7665  SCIP_CONSDATA* consdata;
7666  SCIP_Bool violated;
7667  int oldncuts;
7668 
7669  assert(scip != NULL);
7670  assert(conshdlrdata != NULL);
7671  assert(cons != NULL);
7672  assert(cutoff != NULL);
7673 
7674  consdata = SCIPconsGetData(cons);
7675  assert(ncuts != NULL);
7676  assert(consdata != NULL);
7677 
7678  oldncuts = *ncuts;
7679  *cutoff = FALSE;
7680 
7681  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7682 
7683  if( violated )
7684  {
7685  /* insert LP row as cut */
7686  SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7687  (*ncuts)++;
7688  }
7689  else if( !SCIPconsIsModifiable(cons) && separatecards )
7690  {
7691  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7692  if( !separateall && sol == NULL )
7693  {
7694  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7695  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7696  {
7697  SCIP_Real dualsol;
7698 
7699  dualsol = SCIProwGetDualsol(consdata->row);
7700  if( SCIPisFeasNegative(scip, dualsol) )
7701  {
7702  if( !SCIPisInfinity(scip, consdata->rhs) )
7703  {
7704  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7705  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7706  }
7707  }
7708  else if( SCIPisFeasPositive(scip, dualsol) )
7709  {
7710  if( !SCIPisInfinity(scip, -consdata->lhs) )
7711  {
7712  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7713  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7714  }
7715  }
7716  }
7717  }
7718  else
7719  {
7720  if( !SCIPisInfinity(scip, consdata->rhs) )
7721  {
7722  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7723  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7724  }
7725  if( !SCIPisInfinity(scip, -consdata->lhs) )
7726  {
7727  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7728  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7729  }
7730  }
7731  }
7732 
7733  if( *ncuts > oldncuts )
7734  {
7735  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7736  }
7737 
7738  return SCIP_OKAY;
7739 }
7740 
7741 /** propagation method for linear constraints */
7742 static
7744  SCIP* scip, /**< SCIP data structure */
7745  SCIP_CONS* cons, /**< linear constraint */
7746  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7747  SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7748  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7749  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7750  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7751  int* nchgbds /**< pointer to count the total number of tightened bounds */
7752  )
7753 {
7754  SCIP_CONSDATA* consdata;
7755  SCIP_Real minactivity;
7756  SCIP_Real maxactivity;
7757  SCIP_Bool isminacttight;
7758  SCIP_Bool ismaxacttight;
7759  SCIP_Bool isminsettoinfinity;
7760  SCIP_Bool ismaxsettoinfinity;
7761 
7762  assert(scip != NULL);
7763  assert(cons != NULL);
7764  assert(cutoff != NULL);
7765  assert(nchgbds != NULL);
7766 
7767  /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7768 
7769  consdata = SCIPconsGetData(cons);
7770  assert(consdata != NULL);
7771 
7772  if( consdata->eventdata == NULL )
7773  {
7774  SCIP_CONSHDLR* conshdlr;
7775  SCIP_CONSHDLRDATA* conshdlrdata;
7776 
7777  conshdlr = SCIPconsGetHdlr(cons);
7778  assert(conshdlr != NULL);
7779 
7780  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7781  assert(conshdlrdata != NULL);
7782 
7783  /* catch bound change events of variables */
7784  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7785  assert(consdata->eventdata != NULL);
7786  }
7787 
7788  *cutoff = FALSE;
7789 
7790  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7791  if( !SCIPconsIsModifiable(cons) )
7792  {
7793  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7794  if( !SCIPinRepropagation(scip) )
7795  {
7796  SCIP_CALL( SCIPincConsAge(scip, cons) );
7797  }
7798 
7799  /* tighten the variable's bounds */
7800  if( tightenbounds )
7801  {
7802  int oldnchgbds;
7803 
7804  oldnchgbds = *nchgbds;
7805 
7806  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7807 
7808  if( *nchgbds > oldnchgbds )
7809  {
7810  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7811  }
7812  }
7813 
7814  /* propagate ranged rows */
7815  if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7816  {
7817  int nfixedvars;
7818  int naddconss;
7819  SCIPdebug( int oldnchgbds = *nchgbds; )
7820 
7821  nfixedvars = 0;
7822  naddconss = 0;
7823 
7824  SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7825 
7826  if( *cutoff )
7827  {
7828  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7829  }
7830  else
7831  {
7832  SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7833  }
7834 
7835  if( nfixedvars > 0 )
7836  *nchgbds += 2*nfixedvars;
7837  } /*lint !e438*/
7838 
7839  /* check constraint for infeasibility and redundancy */
7840  if( !(*cutoff) )
7841  {
7842  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
7843  &isminsettoinfinity, &ismaxsettoinfinity);
7844 
7845  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7846  {
7847  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7848  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7849 
7850  /* analyze conflict */
7851  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7852 
7853  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7854  *cutoff = TRUE;
7855  }
7856  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7857  {
7858  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7859  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7860 
7861  /* analyze conflict */
7862  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7863 
7864  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7865  *cutoff = TRUE;
7866  }
7867  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7868  {
7869  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7870  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7871 
7872  /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7873  if( consdata->nvars > 0 )
7874  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7875  else
7876  SCIP_CALL( SCIPdelCons(scip, cons) );
7877  }
7878  }
7879  }
7880 
7881  return SCIP_OKAY;
7882 }
7883 
7884 
7885 /*
7886  * Presolving methods
7887  */
7888 
7889 /** converts all variables with fixed domain into FIXED variables */
7890 static
7892  SCIP* scip, /**< SCIP data structure */
7893  SCIP_CONS* cons, /**< linear constraint */
7894  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7895  int* nfixedvars /**< pointer to count the total number of fixed variables */
7896  )
7897 {
7898  SCIP_CONSDATA* consdata;
7899  SCIP_VAR* var;
7900  SCIP_VARSTATUS varstatus;
7901  SCIP_Real lb;
7902  SCIP_Real ub;
7903  SCIP_Bool fixed;
7904  SCIP_Bool infeasible;
7905  int v;
7906 
7907  assert(scip != NULL);
7908  assert(cons != NULL);
7909  assert(cutoff != NULL);
7910  assert(nfixedvars != NULL);
7911 
7912  consdata = SCIPconsGetData(cons);
7913  assert(consdata != NULL);
7914 
7915  for( v = 0; v < consdata->nvars; ++v )
7916  {
7917  assert(consdata->vars != NULL);
7918  var = consdata->vars[v];
7919  varstatus = SCIPvarGetStatus(var);
7920 
7921  if( varstatus != SCIP_VARSTATUS_FIXED )
7922  {
7923  lb = SCIPvarGetLbGlobal(var);
7924  ub = SCIPvarGetUbGlobal(var);
7925  if( SCIPisEQ(scip, lb, ub) )
7926  {
7927  SCIP_Real fixval;
7928 
7929  fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7930  SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7931  SCIPvarGetName(var), lb, ub, fixval);
7932  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7933  if( infeasible )
7934  {
7935  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7936  *cutoff = TRUE;
7937  return SCIP_OKAY;
7938  }
7939  if( fixed )
7940  (*nfixedvars)++;
7941  }
7942  }
7943  }
7944 
7945  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7946 
7947  if( infeasible )
7948  {
7949  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7950  *cutoff = TRUE;
7951  return SCIP_OKAY;
7952  }
7953 
7954  assert(consdata->removedfixings);
7955 
7956  return SCIP_OKAY;
7957 }
7958 
7959 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7960 
7961 /** extracts cliques of the constraint and adds them to SCIP
7962  *
7963  * The following clique extraction mechanism are implemeneted
7964  *
7965  * 1. collect binary variables and sort them in non increasing order, then
7966  *
7967  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7968  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7969  * condition
7970  *
7971  * minactivity + vals[i] + vals[i+1] > rhs
7972  *
7973  * and also add the binary to binary implication also for non-successive variables for which the same argument
7974  * holds
7975  *
7976  * minactivity + vals[i] + vals[j] > rhs
7977  *
7978  * 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
7979  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7980  *
7981  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7982  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7983  * condition
7984  *
7985  * maxactivity + vals[i] + vals[i-1] < lhs
7986  *
7987  * and also add the binary to binary implication also for non-successive variables for which the same argument
7988  * holds
7989  *
7990  * maxactivity + vals[i] + vals[j] < lhs
7991  *
7992  * e.g. you could multiply the above example by -1
7993  *
7994  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7995  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7996  * condition
7997  *
7998  * minactivity - vals[i] - vals[i-1] > rhs
7999  *
8000  * and also add the binary to binary implication also for non-successive variables for which the
8001  * same argument holds
8002  *
8003  * minactivity - vals[i] - vals[j] > rhs
8004  *
8005  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
8006  * implication x1 = 0 => x3 = 1
8007  *
8008  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
8009  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
8010  * condition
8011  *
8012  * maxactivity - vals[i] - vals[i+1] < lhs
8013  *
8014  * and also add the binary to binary implication also for non-successive variables for which the same argument
8015  * holds
8016  *
8017  * maxactivity - vals[i] - vals[j] < lhs
8018  *
8019  * e.g. you could multiply the above example by -1
8020  *
8021  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
8022  * as clique, (this part is done at the end of the method)
8023  *
8024  */
8025 static
8027  SCIP* scip, /**< SCIP data structure */
8028  SCIP_CONS* cons, /**< linear constraint */
8029  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
8030  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
8031  int* nfixedvars, /**< pointer to count number of fixed variables */
8032  int* nchgbds, /**< pointer to count the total number of tightened bounds */
8033  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
8034  )
8035 {
8036  SCIP_VAR** vars;
8037  SCIP_Real* vals;
8038  SCIP_CONSDATA* consdata;
8039  SCIP_Bool lhsclique;
8040  SCIP_Bool rhsclique;
8041  SCIP_Bool finitelhs;
8042  SCIP_Bool finiterhs;
8043  SCIP_Bool finiteminact;
8044  SCIP_Bool finitemaxact;
8045  SCIP_Bool finitenegminact;
8046  SCIP_Bool finitenegmaxact;
8047  SCIP_Bool finiteposminact;
8048  SCIP_Bool finiteposmaxact;
8049  SCIP_Bool infeasible;
8050  SCIP_Bool stopped;
8051  int cliquenonzerosadded;
8052  int v;
8053  int i;
8054  int nposcoefs;
8055  int nnegcoefs;
8056  int nvars;
8057 
8058  assert(scip != NULL);
8059  assert(cons != NULL);
8060  assert(nfixedvars != NULL);
8061  assert(nchgbds != NULL);
8062  assert(cutoff != NULL);
8063  assert(!SCIPconsIsDeleted(cons));
8064 
8065  consdata = SCIPconsGetData(cons);
8066  assert(consdata != NULL);
8067 
8068  if( consdata->nvars < 2 )
8069  return SCIP_OKAY;
8070 
8071  /* add implications if possible
8072  *
8073  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
8074  * maximal absolute contribution and also only if this variable would force all other variables to their bound
8075  * corresponding to the global minimal activity of the constraint
8076  */
8077  if( !consdata->implsadded )
8078  {
8079  /* sort variables by variable type */
8080  SCIP_CALL( consdataSort(scip, consdata) );
8081 
8082  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
8083  * up front, might change sorting correspondingly
8084  */
8085  /* fast abort if no binaries seem to exist
8086  * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
8087  * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
8088  * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
8089  * which is the requirement for consdataSort() to actually resort the variables
8090  * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
8091  */
8092  if( !SCIPvarIsBinary(consdata->vars[0]) )
8093  return SCIP_OKAY;
8094 
8095  nvars = consdata->nvars;
8096  vars = consdata->vars;
8097  vals = consdata->vals;
8098 
8099  /* recompute activities if needed */
8100  if( !consdata->validactivities )
8101  consdataCalcActivities(scip, consdata);
8102  assert(consdata->validactivities);
8103 
8104  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8105  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8106  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8107  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8108  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8109  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8110  finiteminact = (finitenegminact && finiteposminact);
8111  finitemaxact = (finitenegmaxact && finiteposmaxact);
8112 
8113  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8114  {
8115  SCIP_Real maxabscontrib = -1.0;
8116  SCIP_Bool posval = FALSE;
8117  SCIP_Bool allbinary = TRUE;
8118  int oldnchgbds = *nchgbds;
8119  int nbdchgs = 0;
8120  int nimpls = 0;
8121  int position = -1;
8122 
8123  /* we need a valid minimal/maximal activity to add cliques */
8124  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8125  {
8126  consdataRecomputeGlbMinactivity(scip, consdata);
8127  assert(consdata->validglbminact);
8128  }
8129 
8130  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8131  {
8132  consdataRecomputeGlbMaxactivity(scip, consdata);
8133  assert(consdata->validglbmaxact);
8134  }
8135  assert(consdata->validglbminact || consdata->validglbmaxact);
8136 
8137  /* @todo extend this to local/constraint probing */
8138 
8139  /* determine maximal contribution to the activity */
8140  for( v = nvars - 1; v >= 0; --v )
8141  {
8142  if( SCIPvarIsBinary(vars[v]) )
8143  {
8144  if( vals[v] > 0 )
8145  {
8146  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8147 
8148  if( value > maxabscontrib )
8149  {
8150  maxabscontrib = value;
8151  position = v;
8152  posval = TRUE;
8153  }
8154  }
8155  else
8156  {
8157  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8158 
8159  value = REALABS(value);
8160 
8161  if( value > maxabscontrib )
8162  {
8163  maxabscontrib = value;
8164  position = v;
8165  posval = FALSE;
8166  }
8167  }
8168  }
8169  else
8170  allbinary = FALSE;
8171  }
8172  assert(0 <= position && position < nvars);
8173 
8174  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8175  {
8176  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8177  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8178  * implications
8179  */
8180  if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8181  {
8182  for( v = nvars - 1; v >= 0; --v )
8183  {
8184  /* binary to binary implications will be collected when extrating cliques */
8185  if( !SCIPvarIsBinary(vars[v]) )
8186  {
8187  if( v != position )
8188  {
8189  if( vals[v] > 0 )
8190  {
8191  /* add implications */
8192  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8193  ++nimpls;
8194  *nchgbds += nbdchgs;
8195  }
8196  else
8197  {
8198  /* add implications */
8199  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8200  ++nimpls;
8201  *nchgbds += nbdchgs;
8202  }
8203 
8204  if( infeasible )
8205  {
8206  *cutoff = TRUE;
8207  break;
8208  }
8209  }
8210  }
8211  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8212  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8213  break;
8214  }
8215  }
8216 
8217  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8218  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8219  * implications
8220  */
8221  if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8222  {
8223  for( v = nvars - 1; v >= 0; --v )
8224  {
8225  /* binary to binary implications will be collected when extrating cliques */
8226  if( !SCIPvarIsBinary(vars[v]) )
8227  {
8228  if( v != position )
8229  {
8230  if( vals[v] > 0 )
8231  {
8232  /* add implications */
8233  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8234  ++nimpls;
8235  *nchgbds += nbdchgs;
8236  }
8237  else
8238  {
8239  /* add implications */
8240  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8241  ++nimpls;
8242  *nchgbds += nbdchgs;
8243  }
8244 
8245  if( infeasible )
8246  {
8247  *cutoff = TRUE;
8248  break;
8249  }
8250  }
8251  }
8252  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8253  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8254  break;
8255  }
8256  }
8257 
8258  /* did we find some implications */
8259  if( nimpls > 0 )
8260  {
8261  SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8262 
8263  if( *cutoff )
8264  return SCIP_OKAY;
8265 
8266  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8267  if( *nchgbds - oldnchgbds > 0 )
8268  {
8269  /* check for fixed variables */
8270  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8271  if( *cutoff )
8272  return SCIP_OKAY;
8273 
8274  /* tighten variable's bounds */
8275  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8276  if( *cutoff )
8277  return SCIP_OKAY;
8278 
8279  /* check for fixed variables */
8280  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8281  if( *cutoff )
8282  return SCIP_OKAY;
8283  }
8284  }
8285  }
8286  }
8287 
8288  consdata->implsadded = TRUE;
8289  }
8290 
8291  /* check if we already added the cliques of this constraint */
8292  if( consdata->cliquesadded )
8293  return SCIP_OKAY;
8294 
8295  consdata->cliquesadded = TRUE;
8296  cliquenonzerosadded = 0;
8297  stopped = FALSE;
8298 
8299  /* sort variables by variable type */
8300  SCIP_CALL( consdataSort(scip, consdata) );
8301 
8302  nvars = consdata->nvars;
8303  vars = consdata->vars;
8304  vals = consdata->vals;
8305 
8306  /**@todo extract more cliques, implications and variable bounds from linear constraints */
8307 
8308  /* recompute activities if needed */
8309  if( !consdata->validactivities )
8310  consdataCalcActivities(scip, consdata);
8311  assert(consdata->validactivities);
8312 
8313  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8314  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8315  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8316  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8317  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8318  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8319  finiteminact = (finitenegminact && finiteposminact);
8320  finitemaxact = (finitenegmaxact && finiteposmaxact);
8321 
8322  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8323  * information
8324  */
8325  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8326  {
8327  SCIP_VAR** binvars;
8328  SCIP_Real* binvarvals;
8329  int nposbinvars = 0;
8330  int nnegbinvars = 0;
8331  int allonebinary = 0;
8332 
8333  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8334  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8335 
8336  /* collect binary variables */
8337  for( i = 0; i < nvars; ++i )
8338  {
8339  if( SCIPvarIsBinary(vars[i]) )
8340  {
8341  assert(!SCIPisZero(scip, vals[i]));
8342 
8343  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8344  ++allonebinary;
8345 
8346  binvars[nposbinvars + nnegbinvars] = vars[i];
8347  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8348 
8349  if( SCIPisPositive(scip, vals[i]) )
8350  ++nposbinvars;
8351  else
8352  ++nnegbinvars;
8353 
8354  assert(nposbinvars + nnegbinvars <= nvars);
8355  }
8356  /* stop searching for binary variables, because the constraint data is sorted */
8357  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8358  break;
8359  }
8360  assert(nposbinvars + nnegbinvars <= nvars);
8361 
8362  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8363  * cliques
8364  */
8365  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8366  {
8367  SCIP_Real threshold;
8368  int oldnchgbds = *nchgbds;
8369  int nbdchgs;
8370  int jstart;
8371  int j;
8372 
8373  /* we need a valid minimal/maximal activity to add cliques */
8374  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8375  {
8376  consdataRecomputeGlbMinactivity(scip, consdata);
8377  assert(consdata->validglbminact);
8378  }
8379 
8380  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8381  {
8382  consdataRecomputeGlbMaxactivity(scip, consdata);
8383  assert(consdata->validglbmaxact);
8384  }
8385  assert(consdata->validglbminact || consdata->validglbmaxact);
8386 
8387  /* sort coefficients non-increasing to be faster in the clique search */
8388  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8389 
8390  /* case a) */
8391  if( finiterhs && finitenegminact && nposbinvars >= 2 )
8392  {
8393  /* compute value that needs to be exceeded */
8394  threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8395 
8396  j = 1;
8397 #ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8398  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8399  assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8400 #endif
8401  /* check if at least two variables are in a clique */
8402  if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8403  {
8404  ++j;
8405  /* check for extending the clique */
8406  while( j < nposbinvars )
8407  {
8408  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8409  break;
8410  ++j;
8411  }
8412  assert(j >= 2);
8413 
8414  /* add clique with at least two variables */
8415  SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8416 
8417  if( infeasible )
8418  *cutoff = TRUE;
8419 
8420  *nchgbds += nbdchgs;
8421 
8422  cliquenonzerosadded += j;
8423  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8424  stopped = TRUE;
8425 
8426  /* exchange the last variable in the clique if possible and add all new ones */
8427  if( !stopped && !(*cutoff) && j < nposbinvars )
8428  {
8429  SCIP_VAR** clqvars;
8430  int lastfit = j - 2;
8431  assert(lastfit >= 0);
8432 
8433  /* copy all 'main'-clique variables */
8434  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8435 
8436  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8437  while( lastfit >= 0 && j < nposbinvars )
8438  {
8439  /* check if two variables are in a clique */
8440  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8441  {
8442  clqvars[lastfit + 1] = binvars[j];
8443 
8444  /* add clique with at least two variables */
8445  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8446 
8447  if( infeasible )
8448  {
8449  *cutoff = TRUE;
8450  break;
8451  }
8452 
8453  *nchgbds += nbdchgs;
8454 
8455  cliquenonzerosadded += (lastfit + 2);
8456  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8457  {
8458  stopped = TRUE;
8459  break;
8460  }
8461 
8462  ++j;
8463  }
8464  else
8465  --lastfit;
8466  }
8467 
8468  SCIPfreeBufferArray(scip, &clqvars);
8469  }
8470  }
8471  }
8472 
8473  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8474  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8475  {
8476  /* check for fixed variables */
8477  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8478 
8479  if( !*cutoff )
8480  {
8481  /* tighten variable's bounds */
8482  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8483 
8484  if( !*cutoff )
8485  {
8486  /* check for fixed variables */
8487  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8488 
8489  if( !*cutoff )
8490  {
8491  /* sort variables by variable type */
8492  SCIP_CALL( consdataSort(scip, consdata) );
8493 
8494  /* recompute activities if needed */
8495  if( !consdata->validactivities )
8496  consdataCalcActivities(scip, consdata);
8497  assert(consdata->validactivities);
8498 
8499  nvars = consdata->nvars;
8500  vars = consdata->vars;
8501  vals = consdata->vals;
8502  nposbinvars = 0;
8503  nnegbinvars = 0;
8504  allonebinary = 0;
8505 
8506  /* update binary variables */
8507  for( i = 0; i < nvars; ++i )
8508  {
8509  if( SCIPvarIsBinary(vars[i]) )
8510  {
8511  assert(!SCIPisZero(scip, vals[i]));
8512 
8513  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8514  ++allonebinary;
8515 
8516  binvars[nposbinvars + nnegbinvars] = vars[i];
8517  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8518 
8519  if( SCIPisPositive(scip, vals[i]) )
8520  ++nposbinvars;
8521  else
8522  ++nnegbinvars;
8523 
8524  assert(nposbinvars + nnegbinvars <= nvars);
8525  }
8526  /* stop searching for binary variables, because the constraint data is sorted */
8527  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8528  break;
8529  }
8530  assert(nposbinvars + nnegbinvars <= nvars);
8531  }
8532  }
8533  }
8534 
8535  oldnchgbds = *nchgbds;
8536  }
8537 
8538  /* case b) */
8539  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8540  {
8541  /* compute value that needs to be deceeded */
8542  threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8543 
8544  i = nposbinvars + nnegbinvars - 1;
8545  j = i - 1;
8546 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8547  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8548  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8549 #endif
8550  /* check if two variables are in a clique */
8551  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8552  {
8553  --j;
8554  /* check for extending the clique */
8555  while( j >= nposbinvars )
8556  {
8557  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8558  break;
8559  --j;
8560  }
8561  jstart = j;
8562 
8563  assert(i - j >= 2);
8564  /* add clique with at least two variables */
8565  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8566 
8567  if( infeasible )
8568  *cutoff = TRUE;
8569 
8570  *nchgbds += nbdchgs;
8571 
8572  cliquenonzerosadded += (i - j);
8573  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8574  stopped = TRUE;
8575 
8576  /* exchange the last variable in the clique if possible and add all new ones */
8577  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8578  {
8579  SCIP_VAR** clqvars;
8580  int lastfit = jstart + 1;
8581  assert(lastfit < i);
8582 
8583  /* copy all 'main'-clique variables */
8584  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8585  ++lastfit;
8586 
8587  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8588  while( lastfit <= i && j >= nposbinvars )
8589  {
8590  /* check if two variables are in a clique */
8591  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8592  {
8593  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8594  clqvars[lastfit - jstart - 2] = binvars[j];
8595 
8596  assert(i - lastfit + 2 >= 2);
8597  /* add clique with at least two variables */
8598  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8599 
8600  if( infeasible )
8601  {
8602  *cutoff = TRUE;
8603  break;
8604  }
8605 
8606  *nchgbds += nbdchgs;
8607 
8608  cliquenonzerosadded += (i - lastfit + 2);
8609  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8610  {
8611  stopped = TRUE;
8612  break;
8613  }
8614 
8615  --j;
8616  }
8617  else
8618  ++lastfit;
8619  }
8620 
8621  SCIPfreeBufferArray(scip, &clqvars);
8622  }
8623  }
8624  }
8625 
8626  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8627  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8628  {
8629  /* check for fixed variables */
8630  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8631 
8632  if( !*cutoff )
8633  {
8634  /* tighten variable's bounds */
8635  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8636 
8637  if( !*cutoff )
8638  {
8639  /* check for fixed variables */
8640  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8641 
8642  if( !*cutoff )
8643  {
8644  /* sort variables by variable type */
8645  SCIP_CALL( consdataSort(scip, consdata) );
8646 
8647  /* recompute activities if needed */
8648  if( !consdata->validactivities )
8649  consdataCalcActivities(scip, consdata);
8650  assert(consdata->validactivities);
8651 
8652  nvars = consdata->nvars;
8653  vars = consdata->vars;
8654  vals = consdata->vals;
8655  nposbinvars = 0;
8656  nnegbinvars = 0;
8657  allonebinary = 0;
8658 
8659  /* update binary variables */
8660  for( i = 0; i < nvars; ++i )
8661  {
8662  if( SCIPvarIsBinary(vars[i]) )
8663  {
8664  assert(!SCIPisZero(scip, vals[i]));
8665 
8666  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8667  ++allonebinary;
8668 
8669  binvars[nposbinvars + nnegbinvars] = vars[i];
8670  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8671 
8672  if( SCIPisPositive(scip, vals[i]) )
8673  ++nposbinvars;
8674  else
8675  ++nnegbinvars;
8676 
8677  assert(nposbinvars + nnegbinvars <= nvars);
8678  }
8679  /* stop searching for binary variables, because the constraint data is sorted */
8680  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8681  break;
8682  }
8683  assert(nposbinvars + nnegbinvars <= nvars);
8684  }
8685  }
8686  }
8687 
8688  oldnchgbds = *nchgbds;
8689  }
8690 
8691  /* case c) */
8692  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8693  {
8694  SCIP_Bool* values;
8695 
8696  /* initialize clique values array for adding a negated clique */
8697  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8698  BMSclearMemoryArray(values, nnegbinvars);
8699 
8700  /* compute value that needs to be exceeded */
8701  threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8702 
8703  i = nposbinvars + nnegbinvars - 1;
8704  j = i - 1;
8705 
8706 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8707  /* check if the variable should not have already been fixed to one */
8708  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8709 #endif
8710 
8711  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8712  {
8713  --j;
8714  /* check for extending the clique */
8715  while( j >= nposbinvars )
8716  {
8717  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8718  break;
8719  --j;
8720  }
8721  jstart = j;
8722 
8723  assert(i - j >= 2);
8724  /* add negated clique with at least two variables */
8725  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8726 
8727  if( infeasible )
8728  *cutoff = TRUE;
8729 
8730  *nchgbds += nbdchgs;
8731 
8732  cliquenonzerosadded += (i - j);
8733  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8734  stopped = TRUE;
8735 
8736  /* exchange the last variable in the clique if possible and add all new ones */
8737  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8738  {
8739  SCIP_VAR** clqvars;
8740  int lastfit = j + 1;
8741  assert(lastfit < i);
8742 
8743  /* copy all 'main'-clique variables */
8744  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8745  ++lastfit;
8746 
8747  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8748  while( lastfit <= i && j >= nposbinvars )
8749  {
8750  /* check if two variables are in a negated clique */
8751  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8752  {
8753  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8754  clqvars[lastfit - jstart - 2] = binvars[j];
8755 
8756  assert(i - lastfit + 2 >= 2);
8757  /* add clique with at least two variables */
8758  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8759 
8760  if( infeasible )
8761  {
8762  *cutoff = TRUE;
8763  break;
8764  }
8765 
8766  *nchgbds += nbdchgs;
8767 
8768  cliquenonzerosadded += (i - lastfit + 2);
8769  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8770  {
8771  stopped = TRUE;
8772  break;
8773  }
8774 
8775  --j;
8776  }
8777  else
8778  ++lastfit;
8779  }
8780 
8781  SCIPfreeBufferArray(scip, &clqvars);
8782  }
8783  }
8784 
8785  SCIPfreeBufferArray(scip, &values);
8786  }
8787 
8788  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8789  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8790  {
8791  /* check for fixed variables */
8792  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8793 
8794  if( !*cutoff )
8795  {
8796  /* tighten variable's bounds */
8797  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8798 
8799  if( !*cutoff )
8800  {
8801  /* check for fixed variables */
8802  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8803 
8804  if( !*cutoff )
8805  {
8806  /* sort variables by variable type */
8807  SCIP_CALL( consdataSort(scip, consdata) );
8808 
8809  /* recompute activities if needed */
8810  if( !consdata->validactivities )
8811  consdataCalcActivities(scip, consdata);
8812  assert(consdata->validactivities);
8813 
8814  nvars = consdata->nvars;
8815  vars = consdata->vars;
8816  vals = consdata->vals;
8817  nposbinvars = 0;
8818  nnegbinvars = 0;
8819  allonebinary = 0;
8820 
8821  /* update binary variables */
8822  for( i = 0; i < nvars; ++i )
8823  {
8824  if( SCIPvarIsBinary(vars[i]) )
8825  {
8826  assert(!SCIPisZero(scip, vals[i]));
8827 
8828  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8829  ++allonebinary;
8830 
8831  binvars[nposbinvars + nnegbinvars] = vars[i];
8832  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8833 
8834  if( SCIPisPositive(scip, vals[i]) )
8835  ++nposbinvars;
8836  else
8837  ++nnegbinvars;
8838 
8839  assert(nposbinvars + nnegbinvars <= nvars);
8840  }
8841  /* stop searching for binary variables, because the constraint data is sorted */
8842  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8843  break;
8844  }
8845  assert(nposbinvars + nnegbinvars <= nvars);
8846  }
8847  }
8848  }
8849  }
8850 
8851  /* case d) */
8852  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8853  {
8854  SCIP_Bool* values;
8855 
8856  /* initialize clique values array for adding a negated clique */
8857  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8858  BMSclearMemoryArray(values, nposbinvars);
8859 
8860  /* compute value that needs to be exceeded */
8861  threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8862 
8863  j = 1;
8864 
8865 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8866  /* check if the variable should not have already been fixed to one */
8867  assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8868 #endif
8869 
8870  if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8871  {
8872  ++j;
8873  /* check for extending the clique */
8874  while( j < nposbinvars )
8875  {
8876  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8877  break;
8878  ++j;
8879  }
8880  assert(j >= 2);
8881 
8882  /* add negated clique with at least two variables */
8883  SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8884 
8885  if( infeasible )
8886  *cutoff = TRUE;
8887 
8888  *nchgbds += nbdchgs;
8889 
8890  cliquenonzerosadded += j;
8891  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8892  stopped = TRUE;
8893 
8894  /* exchange the last variable in the clique if possible and add all new ones */
8895  if( !stopped && !(*cutoff) && j < nposbinvars )
8896  {
8897  SCIP_VAR** clqvars;
8898  int lastfit = j - 2;
8899  assert(lastfit >= 0);
8900 
8901  /* copy all 'main'-clique variables */
8902  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8903 
8904  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8905  while( lastfit >= 0 && j < nposbinvars )
8906  {
8907  /* check if two variables are in a negated clique */
8908  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8909  {
8910  clqvars[lastfit + 1] = binvars[j];
8911 
8912  /* add clique with at least two variables */
8913  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8914 
8915  if( infeasible )
8916  {
8917  *cutoff = TRUE;
8918  break;
8919  }
8920 
8921  *nchgbds += nbdchgs;
8922 
8923  cliquenonzerosadded += lastfit + 2;
8924  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8925  break;
8926 
8927  ++j;
8928  }
8929  else
8930  --lastfit;
8931  }
8932 
8933  SCIPfreeBufferArray(scip, &clqvars);
8934  }
8935  }
8936 
8937  SCIPfreeBufferArray(scip, &values);
8938  }
8939  }
8940 
8941  SCIPfreeBufferArray(scip, &binvarvals);
8942  SCIPfreeBufferArray(scip, &binvars);
8943 
8944  if( *cutoff )
8945  return SCIP_OKAY;
8946  }
8947 
8948  /* 2. we only check if the constraint is a set packing / partitioning constraint */
8949 
8950  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8951  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8952  */
8953  nposcoefs = 0;
8954  nnegcoefs = 0;
8955  for( i = 0; i < nvars; ++i )
8956  {
8957  if( !SCIPvarIsBinary(vars[i]) )
8958  return SCIP_OKAY;
8959  else if( SCIPisEQ(scip, vals[i], +1.0) )
8960  nposcoefs++;
8961  else if( SCIPisEQ(scip, vals[i], -1.0) )
8962  nnegcoefs++;
8963  else
8964  return SCIP_OKAY;
8965  }
8966 
8967  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8968  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8969 
8970  if( lhsclique || rhsclique )
8971  {
8972  SCIP_Bool* values;
8973  int nbdchgs;
8974 
8975  SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8976  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8977  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8978 
8979  for( i = 0; i < nvars; ++i )
8980  values[i] = (rhsclique == (vals[i] > 0.0));
8981 
8982  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8983 
8984  if( infeasible )
8985  *cutoff = TRUE;
8986 
8987  *nchgbds += nbdchgs;
8988  SCIPfreeBufferArray(scip, &values);
8989  }
8990 
8991  return SCIP_OKAY;
8992 }
8993 
8994 /** tightens left and right hand side of constraint due to integrality */
8995 static
8997  SCIP* scip, /**< SCIP data structure */
8998  SCIP_CONS* cons, /**< linear constraint */
8999  int* nchgsides, /**< pointer to count number of side changes */
9000  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
9001  )
9002 {
9003  SCIP_CONSDATA* consdata;
9004  SCIP_Real newlhs;
9005  SCIP_Real newrhs;
9006  SCIP_Bool chglhs;
9007  SCIP_Bool chgrhs;
9008  SCIP_Bool integral;
9009  int i;
9010 
9011  assert(scip != NULL);
9012  assert(cons != NULL);
9013  assert(nchgsides != NULL);
9014  assert(infeasible != NULL);
9016  consdata = SCIPconsGetData(cons);
9017  assert(consdata != NULL);
9018 
9019  *infeasible = FALSE;
9020 
9021  chglhs = FALSE;
9022  chgrhs = FALSE;
9023  newlhs = -SCIPinfinity(scip);
9024  newrhs = SCIPinfinity(scip);
9025 
9026  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
9027  {
9028  integral = TRUE;
9029  for( i = 0; i < consdata->nvars && integral; ++i )
9030  {
9031  integral = SCIPisIntegral(scip, consdata->vals[i])
9032  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
9033  }
9034  if( integral )
9035  {
9036  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
9037  {
9038  newlhs = SCIPfeasCeil(scip, consdata->lhs);
9039  chglhs = TRUE;
9040  }
9041  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
9042  {
9043  newrhs = SCIPfeasFloor(scip, consdata->rhs);
9044  chgrhs = TRUE;
9045  }
9046 
9047  /* check whether rounding would lead to an unsatisfiable constraint */
9048  if( SCIPisGT(scip, newlhs, newrhs) )
9049  {
9050  SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
9051  "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
9052 
9053  *infeasible = TRUE;
9054  return SCIP_OKAY;
9055  }
9056 
9057  SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
9058  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9059 
9060  if( chglhs )
9061  {
9062  assert(!SCIPisInfinity(scip, -newlhs));
9063 
9064  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9065  if( !consdata->upgraded )
9066  (*nchgsides)++;
9067  }
9068  if( chgrhs )
9069  {
9070  assert(!SCIPisInfinity(scip, newrhs));
9071 
9072  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9073  if( !consdata->upgraded )
9074  (*nchgsides)++;
9075  }
9076  SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
9077  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9078  }
9079  }
9080 
9081  return SCIP_OKAY;
9082 }
9083 
9084 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
9085  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
9086  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
9087  * (i) ai >= 0:
9088  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
9089  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
9090  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9091  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9092  * - change coefficients:
9093  * ai' := max(lhs - minact, maxact - rhs)
9094  * lhs' := lhs - (ai - ai')*li
9095  * rhs' := rhs - (ai - ai')*ui
9096  * (ii) ai < 0:
9097  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9098  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9099  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9100  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9101  * - change coefficients:
9102  * ai' := min(rhs - maxact, minact - lhs)
9103  * lhs' := lhs - (ai - ai')*ui
9104  * rhs' := rhs - (ai - ai')*li
9105  *
9106  * We further try to remove redundant variable from the constraint;
9107  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
9108  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9109  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
9110  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
9111  * 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
9112  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
9113  *
9114  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9115  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9116  */
9117 static
9119  SCIP* scip, /**< SCIP data structure */
9120  SCIP_CONS* cons, /**< linear constraint */
9121  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9122  int* nchgsides /**< pointer to count number of side changes */
9123  )
9124 {
9125  SCIP_CONSDATA* consdata;
9126  SCIP_VAR* var;
9127  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9128  * activity, ignoring the coefficients contributing with infinite value */
9129  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9130  * activity, ignoring the coefficients contributing with infinite value */
9131  SCIP_Bool isminacttight; /* are all contributions to the minactivity non-huge or non-contradicting? */
9132  SCIP_Bool ismaxacttight; /* are all contributions to the maxactivity non-huge or non-contradicting? */
9133  SCIP_Bool isminsettoinfinity;
9134  SCIP_Bool ismaxsettoinfinity;
9135  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
9136  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
9137  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
9138  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
9139  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9140  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9141  SCIP_Real val;
9142  SCIP_Real newval;
9143  SCIP_Real newlhs;
9144  SCIP_Real newrhs;
9145  SCIP_Real lb;
9146  SCIP_Real ub;
9147  int i;
9148 
9149  assert(scip != NULL);
9150  assert(cons != NULL);
9151  assert(nchgcoefs != NULL);
9152  assert(nchgsides != NULL);
9153 
9154  consdata = SCIPconsGetData(cons);
9155  assert(consdata != NULL);
9156 
9157  /* @todo Is this still needed with automatic recomputation of activities? */
9158  /* if the maximal coefficient is too large, recompute the activities */
9159  if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9160  || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9161  {
9162  consdataRecomputeMinactivity(scip, consdata);
9163  consdataRecomputeMaxactivity(scip, consdata);
9164  }
9165 
9166  /* get the minimal and maximal activity of the constraint */
9167  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9168  &isminsettoinfinity, &ismaxsettoinfinity);
9169 
9170  minleftactivity = 0.0;
9171  maxleftactivity = 0.0;
9172 
9173  /* try to tighten each coefficient */
9174  i = 0;
9175  while( i < consdata->nvars )
9176  {
9177  var = consdata->vars[i];
9178 
9179  /* get coefficient and variable's bounds */
9180  lb = SCIPvarGetLbLocal(var);
9181  ub = SCIPvarGetUbLocal(var);
9182  val = consdata->vals[i];
9183  assert(!SCIPisZero(scip, val));
9184 
9185  /* check sign of coefficient */
9186  if( val >= 0.0 )
9187  {
9188  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9190  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
9191  {
9192  /* change coefficients:
9193  * ai' := max(lhs - minact, maxact - rhs)
9194  * lhs' := lhs - (ai - ai')*li
9195  * rhs' := rhs - (ai - ai')*ui
9196  */
9197 
9198  lval = consdata->lhs - minactivity;
9199  rval = maxactivity - consdata->rhs;
9200 
9201  /* Try to avoid cancellation, if there are only two variables */
9202  if( consdata->nvars == 2 )
9203  {
9204  SCIP_Real otherval;
9205  otherval = consdata->vals[1-i];
9206 
9207  if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9208  {
9209  lval = consdata->lhs - val*lb;
9210  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9211  }
9212 
9213  if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9214  {
9215  rval = val*ub - consdata->rhs;
9216  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9217  }
9218  }
9219 
9220  newval = MAX(lval, rval);
9221  assert(SCIPisSumRelLE(scip, newval, val));
9222 
9223  /* Try to avoid cancellation in computation of lhs/rhs */
9224  newlhs = consdata->lhs - val * lb;
9225  newlhs += newval * lb;
9226  newrhs = consdata->rhs - val * ub;
9227  newrhs += newval * ub;
9228 
9229  if( !SCIPisSumRelEQ(scip, newval, val) )
9230  {
9231  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9232  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9233  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9234 
9235  /* update the coefficient and the activity bounds */
9236  if( SCIPisZero(scip, newval) )
9237  {
9238  SCIP_CALL( delCoefPos(scip, cons, i) );
9239  i--;
9240  }
9241  else
9242  {
9243  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9244  }
9245  (*nchgcoefs)++;
9246 
9247  /* get the new minimal and maximal activity of the constraint */
9248  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9249  &isminsettoinfinity, &ismaxsettoinfinity);
9250 
9251  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9252  {
9253  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9254 
9255  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9256  (*nchgsides)++;
9257  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9258  }
9259 
9260  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9261  {
9262  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9263 
9264  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9265  (*nchgsides)++;
9266  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9267  }
9268  }
9269  }
9270  else
9271  {
9272  if( !SCIPisInfinity(scip, -minleftactivity) )
9273  {
9274  assert(!SCIPisInfinity(scip, val));
9275  assert(!SCIPisInfinity(scip, lb));
9276  if( SCIPisInfinity(scip, -lb) )
9277  minleftactivity = -SCIPinfinity(scip);
9278  else
9279  minleftactivity += val * lb;
9280  }
9281 
9282  if( !SCIPisInfinity(scip, maxleftactivity) )
9283  {
9284  assert(!SCIPisInfinity(scip, val));
9285  assert(!SCIPisInfinity(scip, -ub));
9286  if( SCIPisInfinity(scip,ub) )
9287  maxleftactivity = SCIPinfinity(scip);
9288  else
9289  maxleftactivity += val * ub;
9290  }
9291  }
9292  }
9293  else
9294  {
9295  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9297  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9298  {
9299  /* change coefficients:
9300  * ai' := min(rhs - maxact, minact - lhs)
9301  * lhs' := lhs - (ai - ai')*ui
9302  * rhs' := rhs - (ai - ai')*li
9303  */
9304 
9305  lval = minactivity - consdata->lhs;
9306  rval = consdata->rhs - maxactivity;
9307 
9308  /* Try to avoid cancellation, if there are only two variables */
9309  if( consdata->nvars == 2 )
9310  {
9311  SCIP_Real otherval;
9312  otherval = consdata->vals[1-i];
9313 
9314  if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9315  {
9316  lval = val*ub - consdata->lhs;
9317  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9318  }
9319 
9320  if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9321  {
9322  rval = consdata->rhs - val*lb;
9323  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9324  }
9325  }
9326 
9327  newval = MIN(lval, rval);
9328  assert(SCIPisSumRelGE(scip, newval, val));
9329 
9330  /* Try to avoid cancellation in computation of lhs/rhs */
9331  newlhs = consdata->lhs - val * ub;
9332  newlhs += newval * ub;
9333  newrhs = consdata->rhs - val * lb;
9334  newrhs += newval * lb;
9335 
9336  if( !SCIPisSumRelEQ(scip, newval, val) )
9337  {
9338  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9339  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9340  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9341 
9342  /* update the coefficient and the activity bounds */
9343  if( SCIPisZero(scip, newval) )
9344  {
9345  SCIP_CALL( delCoefPos(scip, cons, i) );
9346  i--;
9347  }
9348  else
9349  {
9350  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9351  }
9352  (*nchgcoefs)++;
9353 
9354  /* get the new minimal and maximal activity of the constraint */
9355  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9356  &isminsettoinfinity, &ismaxsettoinfinity);
9357 
9358  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9359  {
9360  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9361 
9362  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9363  (*nchgsides)++;
9364  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9365  }
9366 
9367  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9368  {
9369  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9370 
9371  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9372  (*nchgsides)++;
9373  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9374  }
9375  }
9376  }
9377  else
9378  {
9379  if( !SCIPisInfinity(scip, -minleftactivity) )
9380  {
9381  assert(!SCIPisInfinity(scip, -val));
9382  assert(!SCIPisInfinity(scip, -ub));
9383  if( SCIPisInfinity(scip, ub) )
9384  minleftactivity = -SCIPinfinity(scip);
9385  else
9386  minleftactivity += val * ub;
9387  }
9388 
9389  if( !SCIPisInfinity(scip, maxleftactivity) )
9390  {
9391  assert(!SCIPisInfinity(scip, -val));
9392  assert(!SCIPisInfinity(scip, lb));
9393  if( SCIPisInfinity(scip, -lb) )
9394  maxleftactivity = SCIPinfinity(scip);
9395  else
9396  maxleftactivity += val * lb;
9397  }
9398  }
9399  }
9400  ++i;
9401  }
9402 
9403  SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9404  minleftactivity, consdata->rhs);
9405  SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9406  maxleftactivity, consdata->lhs);
9407 
9408  /* minleft == \infty ==> minactivity == \infty */
9409  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9410  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9411 
9412  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9413  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9414  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9415  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9416  */
9417  assert(!SCIPisInfinity(scip, minactivity));
9418  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
9419  return SCIP_OKAY;
9420 
9421  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9422  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9423  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9424  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9425  */
9426  assert(!SCIPisInfinity(scip, -maxactivity));
9427  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
9428  return SCIP_OKAY;
9429 
9430  /* correct lhs and rhs by min/max activity of surely non-redundant variables
9431  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9432  */
9433  aggrlhs = consdata->lhs - minactivity + minleftactivity;
9434  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9435 
9436  /* check if the constraint contains variables which are redundant. The reasoning is the following:
9437  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9438  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9439  * they can be removed from the constraint.
9440  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9441  */
9442  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9443  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9444  {
9445  SCIP_Real minleftactivitypart;
9446  SCIP_Real maxleftactivitypart;
9447 
9448  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9449 
9450  /* try to remove redundant variables from constraint */
9451  i = 0;
9452  while( i < consdata->nvars )
9453  {
9454  var = consdata->vars[i];
9455  minleftactivitypart = 0.0;
9456  maxleftactivitypart = 0.0;
9457  lb = SCIPvarGetLbLocal(var);
9458  ub = SCIPvarGetUbLocal(var);
9459 
9460  /* get coefficient and variable's bounds */
9461  val = consdata->vals[i];
9462  assert(!SCIPisZero(scip, val));
9463 
9464  /* check sign of coefficient */
9465  if( val >= 0.0 )
9466  {
9467  /* negation of condition above in case of positive val */
9469  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9470  {
9471  SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9472  SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9473  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9474  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9475 
9476  minleftactivitypart = val * lb;
9477  maxleftactivitypart = val * ub;
9478 
9479  SCIP_CALL( delCoefPos(scip, cons, i) );
9480  i--;
9481 
9482  /* get the new minimal and maximal activity of the constraint */
9483  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9484  &isminsettoinfinity, &ismaxsettoinfinity);
9485 
9486  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9487  * huge contributions
9488  */
9489  assert(isminacttight || SCIPisInfinity(scip, -consdata->lhs));
9490  assert(ismaxacttight || SCIPisInfinity(scip, consdata->rhs));
9491  }
9492  }
9493  else
9494  {
9495  /* negation of condition above in case of negative val */
9497  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9498  {
9499  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9500  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9501 
9502  minleftactivitypart = val * ub;
9503  maxleftactivitypart = val * lb;
9504 
9505  SCIP_CALL( delCoefPos(scip, cons, i) );
9506  i--;
9507 
9508  /* get the new minimal and maximal activity of the constraint */
9509  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9510  &isminsettoinfinity, &ismaxsettoinfinity);
9511 
9512  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9513  * huge contributions
9514  */
9515  assert(isminacttight || SCIPisInfinity(scip, -consdata->lhs));
9516  assert(ismaxacttight || SCIPisInfinity(scip, consdata->rhs));
9517  }
9518  }
9519 
9520  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9521  * redundant variables could get deleted,
9522  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9523  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9524  * we would also delete y2 and as a result we would have gotten infeasibility */
9525  /* adjust lhs and right hand side */
9526  newlhs = consdata->lhs - minleftactivitypart;
9527  newrhs = consdata->rhs - maxleftactivitypart;
9528 
9529  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9530  {
9531  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9532  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9533  ++(*nchgsides);
9534  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9535  }
9536  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9537  {
9538  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9539  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9540  ++(*nchgsides);
9541  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9542  }
9543  ++i;
9544  }
9545  }
9546 
9547  return SCIP_OKAY;
9548 }
9549 
9550 /** processes equality with only one variable by fixing the variable and deleting the constraint */
9551 static
9553  SCIP* scip, /**< SCIP data structure */
9554  SCIP_CONS* cons, /**< linear constraint */
9555  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9556  int* nfixedvars, /**< pointer to count number of fixed variables */
9557  int* ndelconss /**< pointer to count number of deleted constraints */
9558  )
9559 {
9560  SCIP_CONSDATA* consdata;
9561  SCIP_VAR* var;
9562  SCIP_Real val;
9563  SCIP_Real fixval;
9564  SCIP_Bool infeasible;
9565  SCIP_Bool fixed;
9566 
9567  assert(scip != NULL);
9568  assert(cons != NULL);
9569  assert(cutoff != NULL);
9570  assert(nfixedvars != NULL);
9571  assert(ndelconss != NULL);
9572 
9573  consdata = SCIPconsGetData(cons);
9574  assert(consdata != NULL);
9575  assert(consdata->nvars == 1);
9576  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9577 
9578  /* calculate the value to fix the variable to */
9579  var = consdata->vars[0];
9580  val = consdata->vals[0];
9581  assert(!SCIPisZero(scip, val));
9582  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9583  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9584  SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9585  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9586 
9587  /* fix variable */
9588  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9589  if( infeasible )
9590  {
9591  SCIPdebugMsg(scip, " -> infeasible fixing\n");
9592  *cutoff = TRUE;
9593  return SCIP_OKAY;
9594  }
9595  if( fixed )
9596  (*nfixedvars)++;
9597 
9598  /* disable constraint */
9599  SCIP_CALL( SCIPdelCons(scip, cons) );
9600  if( !consdata->upgraded )
9601  (*ndelconss)++;
9602 
9603  return SCIP_OKAY;
9604 }
9605 
9606 /** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9607 static
9609  SCIP* scip, /**< SCIP data structure */
9610  SCIP_CONS* cons, /**< linear constraint */
9611  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9612  int* naggrvars, /**< pointer to count number of aggregated variables */
9613  int* ndelconss /**< pointer to count number of deleted constraints */
9614  )
9615 {
9616  SCIP_CONSDATA* consdata;
9617  SCIP_Bool infeasible;
9618  SCIP_Bool redundant;
9619  SCIP_Bool aggregated;
9620 
9621  assert(scip != NULL);
9622  assert(cons != NULL);
9623  assert(cutoff != NULL);
9624  assert(naggrvars != NULL);
9625  assert(ndelconss != NULL);
9626 
9627  consdata = SCIPconsGetData(cons);
9628  assert(consdata != NULL);
9629  assert(consdata->nvars == 2);
9630  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9631 
9632  SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9633  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9634  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9635 
9636  /* aggregate the equality */
9637  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9638  consdata->rhs, &infeasible, &redundant, &aggregated) );
9639 
9640  /* check for infeasibility of aggregation */
9641  if( infeasible )
9642  {
9643  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9644  *cutoff = TRUE;
9645  return SCIP_OKAY;
9646  }
9647 
9648  /* count the aggregation */
9649  if( aggregated )
9650  (*naggrvars)++;
9651 
9652  /* delete the constraint, if it is redundant */
9653  if( redundant )
9654  {
9655  SCIP_CALL( SCIPdelCons(scip, cons) );
9656 
9657  if( !consdata->upgraded )
9658  (*ndelconss)++;
9659  }
9660 
9661  return SCIP_OKAY;
9662 }
9663 
9664 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9665 static
9667  SCIP* scip, /**< SCIP data structure */
9668  SCIP_CONSDATA* consdata, /**< linear constraint data */
9669  SCIP_VAR* slackvar, /**< variable to be aggregated out */
9670  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9671  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9672  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9673  )
9674 {
9675  SCIP_Real slackvarlb;
9676  SCIP_Real slackvarub;
9677 
9678  assert(scip != NULL);
9679  assert(consdata != NULL);
9680  assert(newlhs != NULL);
9681  assert(newrhs != NULL);
9682  assert(!SCIPisInfinity(scip, -consdata->lhs));
9683  assert(!SCIPisInfinity(scip, consdata->rhs));
9684 
9685  slackvarlb = SCIPvarGetLbGlobal(slackvar);
9686  slackvarub = SCIPvarGetUbGlobal(slackvar);
9687  if( slackcoef > 0.0 )
9688  {
9689  if( SCIPisInfinity(scip, -slackvarlb) )
9690  *newrhs = SCIPinfinity(scip);
9691  else
9692  *newrhs = consdata->rhs - slackcoef * slackvarlb;
9693  if( SCIPisInfinity(scip, slackvarub) )
9694  *newlhs = -SCIPinfinity(scip);
9695  else
9696  *newlhs = consdata->lhs - slackcoef * slackvarub;
9697  }
9698  else
9699  {
9700  if( SCIPisInfinity(scip, -slackvarlb) )
9701  *newlhs = -SCIPinfinity(scip);
9702  else
9703  *newlhs = consdata->rhs - slackcoef * slackvarlb;
9704  if( SCIPisInfinity(scip, slackvarub) )
9705  *newrhs = SCIPinfinity(scip);
9706  else
9707  *newrhs = consdata->lhs - slackcoef * slackvarub;
9708  }
9709  assert(SCIPisLE(scip, *newlhs, *newrhs));
9710 }
9711 
9712 /** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9713  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9714  * is implicitly integral by this constraint
9715  *
9716  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9717  * can help.
9718  */
9719 static
9721  SCIP* scip, /**< SCIP data structure */
9722  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9723  SCIP_CONS* cons, /**< linear constraint */
9724  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9725  int* naggrvars, /**< pointer to count number of aggregated variables */
9726  int* ndelconss /**< pointer to count number of deleted constraints */
9727  )
9728 {
9729  SCIP_CONSDATA* consdata;
9730  SCIP_VAR** vars;
9731  SCIP_Real* vals;
9732  SCIP_VARTYPE bestslacktype;
9733  SCIP_VARTYPE slacktype;
9734  SCIP_Real lhs;
9735  SCIP_Real rhs;
9736  SCIP_Real bestslackdomrng;
9737  SCIP_Real minabsval;
9738  SCIP_Real maxabsval;
9739  SCIP_Bool bestremovescons;
9740  SCIP_Bool coefszeroone;
9741  SCIP_Bool coefsintegral;
9742  SCIP_Bool varsintegral;
9743  SCIP_Bool infeasible;
9744  SCIP_Bool samevar;
9745  int supinf; /* counter for infinite contributions to the supremum of a possible
9746  * multi-aggregation
9747  */
9748  int infinf; /* counter for infinite contributions to the infimum of a possible
9749  * multi-aggregation
9750  */
9751  int maxnlocksstay;
9752  int maxnlocksremove;
9753  int bestslackpos;
9754  int bestnlocks;
9755  int ncontvars;
9756  int contvarpos;
9757  int nintvars;
9758  int nimplvars;
9759  int intvarpos;
9760  int v;
9761 
9762  assert(scip != NULL);
9763  assert(cons != NULL);
9764  assert(cutoff != NULL);
9765  assert(naggrvars != NULL);
9766 
9767  consdata = SCIPconsGetData(cons);
9768  assert(consdata != NULL);
9769  assert(consdata->nvars > 2);
9770  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9771 
9772  SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9773 
9774  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9775  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9776  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9777  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9778  */
9779  lhs = consdata->lhs;
9780  rhs = consdata->rhs;
9781  maxnlocksstay = 0;
9782  if( consdata->nvars == 3 )
9783  {
9784  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9785  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9786  */
9787  maxnlocksremove = 3;
9788  }
9789  else if( consdata->nvars == 4 )
9790  {
9791  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9792  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9793  */
9794  maxnlocksremove = 2;
9795  }
9796  else
9797  {
9798  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9799  maxnlocksremove = 1;
9800  }
9801 
9802  /* the locks on this constraint can be ignored */
9803  if( SCIPconsIsChecked(cons) )
9804  {
9805  if( !SCIPisInfinity(scip, -lhs) )
9806  {
9807  maxnlocksstay++;
9808  maxnlocksremove++;
9809  }
9810  if( !SCIPisInfinity(scip, rhs) )
9811  {
9812  maxnlocksstay++;
9813  maxnlocksremove++;
9814  }
9815  }
9816 
9817  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9818  vars = consdata->vars;
9819  vals = consdata->vals;
9820  bestslackpos = -1;
9821  bestslacktype = SCIP_VARTYPE_BINARY;
9822  bestnlocks = INT_MAX;
9823  bestremovescons = FALSE;
9824  bestslackdomrng = 0.0;
9825  coefszeroone = TRUE;
9826  coefsintegral = TRUE;
9827  varsintegral = TRUE;
9828  ncontvars = 0;
9829  contvarpos = -1;
9830  nintvars = 0;
9831  nimplvars = 0;
9832  intvarpos = -1;
9833  minabsval = SCIPinfinity(scip);
9834  maxabsval = -1.0;
9835  for( v = 0; v < consdata->nvars; ++v )
9836  {
9837  SCIP_VAR* var;
9838  SCIP_Real val;
9839  SCIP_Real absval;
9840  SCIP_Real varlb;
9841  SCIP_Real varub;
9842  SCIP_Bool iscont;
9843  int nlocks;
9844 
9845  assert(vars != NULL);
9846  assert(vals != NULL);
9847 
9848  var = vars[v];
9849  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9850  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= 1);
9851  varlb = SCIPvarGetLbGlobal(var);
9852  varub = SCIPvarGetUbGlobal(var);
9853 
9854  val = vals[v];
9855  absval = REALABS(val);
9856  assert(SCIPisPositive(scip, absval));
9857 
9858  /* calculate minimal and maximal absolute value */
9859  if( absval < minabsval )
9860  minabsval = absval;
9861  if( absval > maxabsval )
9862  maxabsval = absval;
9863 
9864  /* do not try to multi aggregate, when numerical bad */
9865  if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9866  return SCIP_OKAY;
9867 
9868  slacktype = SCIPvarGetType(var);
9869  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9870  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9871  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9872  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9873 
9874  /* update candidates for continuous -> implint and integer -> implint conversion */
9875  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9876  {
9877  ncontvars++;
9878  contvarpos = v;
9879  }
9880  else if( slacktype == SCIP_VARTYPE_IMPLINT )
9881  {
9882  ++nimplvars;
9883  }
9884  else if( slacktype == SCIP_VARTYPE_INTEGER )
9885  {
9886  nintvars++;
9887  intvarpos = v;
9888  }
9889 
9890  /* check, if variable is already fixed or aggregated */
9891  if( !SCIPvarIsActive(var) )
9892  continue;
9893 
9894  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9896 
9897  if( nlocks > maxnlocksremove )
9898  continue;
9899 
9900  /* check, if variable can be used as a slack variable */
9901  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9902  !SCIPdoNotMultaggrVar(scip, var) )
9903  {
9904  SCIP_Bool better;
9905  SCIP_Bool equal;
9906  SCIP_Real slackdomrng;
9907 
9908  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9909  slackdomrng = SCIPinfinity(scip);
9910  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9911  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9912  return SCIP_OKAY;
9913  else
9914  {
9915  slackdomrng = (varub - varlb)*absval;
9916  assert(!SCIPisInfinity(scip, slackdomrng));
9917  }
9918  equal = FALSE;
9919  better = (slacktype > bestslacktype) || (bestslackpos == -1);
9920  if( !better && slacktype == bestslacktype )
9921  {
9922  better = (nlocks < bestnlocks);
9923  if( nlocks == bestnlocks && !bestremovescons )
9924  {
9925  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9926  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9927  }
9928  }
9929 
9930  if( better || equal )
9931  {
9932  SCIP_Real minresactivity;
9933  SCIP_Real maxresactivity;
9934  SCIP_Real newlhs;
9935  SCIP_Real newrhs;
9936  SCIP_Bool removescons;
9937  SCIP_Bool ismintight;
9938  SCIP_Bool ismaxtight;
9939  SCIP_Bool isminsettoinfinity;
9940  SCIP_Bool ismaxsettoinfinity;
9941 
9942  /* check if the constraint becomes redundant after multi-aggregation */
9943  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9944  &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
9945 
9946  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9947  * activity
9948  */
9949  if( !ismintight || !ismaxtight )
9950  continue;
9951 
9952  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9953  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9954 
9955  /* check resactivities for reliability */
9956  if( removescons )
9957  {
9958  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9959  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9960 
9961  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9962  && SCIPisFeasLE(scip, newlhs, minresactivity))
9963  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9964 
9965  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9966  }
9967 
9968  /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9969  if( conshdlrdata->multaggrremove && !removescons )
9970  continue;
9971 
9972  /* prefer variables that make the constraints redundant */
9973  if( bestremovescons && !removescons )
9974  continue;
9975 
9976  /* if the constraint does not become redundant, only accept the variable if it does not appear in
9977  * other constraints
9978  */
9979  if( !removescons && nlocks > maxnlocksstay )
9980  continue;
9981 
9982  better = better || (!bestremovescons && removescons);
9983  if( better )
9984  {
9985  bestslackpos = v;
9986  bestslacktype = slacktype;
9987  bestnlocks = nlocks;
9988  bestslackdomrng = slackdomrng;
9989  bestremovescons = removescons;
9990  }
9991  }
9992  }
9993  }
9994 
9995  /* if all coefficients and variables are integral, the right hand side must also be integral */
9996  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9997  {
9998  SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9999  SCIPdebugPrintCons(scip, cons, NULL);
10000  *cutoff = TRUE;
10001  return SCIP_OKAY;
10002  }
10003 
10004  supinf = 0;
10005  infinf = 0;
10006  samevar = FALSE;
10007 
10008  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
10009  for( v = 0; v < consdata->nvars; ++v )
10010  {
10011  if( v != bestslackpos )
10012  {
10013  if( SCIPisPositive(scip, consdata->vals[v]) )
10014  {
10015  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10016  {
10017  ++supinf;
10018  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10019  {
10020  ++infinf;
10021  samevar = TRUE;
10022  }
10023  }
10024  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10025  ++infinf;
10026  }
10027  else if( SCIPisNegative(scip, consdata->vals[v]) )
10028  {
10029  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10030  {
10031  ++supinf;
10032  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10033  {
10034  ++infinf;
10035  samevar = TRUE;
10036  }
10037  }
10038  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10039  ++infinf;
10040  }
10041  }
10042  }
10043  assert(!samevar || (supinf > 0 && infinf > 0));
10044 
10045  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10046  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10047  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
10048  {
10049  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10050  return SCIP_OKAY;
10051  }
10052 
10053  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
10054  * we cannot aggregate the variable, because the integrality condition would get lost
10055  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
10056  * loose the integrality condition for this variable.
10057  */
10058  if( bestslackpos >= 0
10059  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
10060  || (coefsintegral && varsintegral && nimplvars == 0)) )
10061  {
10062  SCIP_VAR* slackvar;
10063  SCIP_Real* scalars;
10064  SCIP_Real slackcoef;
10065  SCIP_Real aggrconst;
10066  SCIP_Real newlhs;
10067  SCIP_Real newrhs;
10068  SCIP_Bool aggregated;
10069 
10070  /* we found a slack variable that only occurs in at most one other constraint:
10071  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
10072  */
10073  assert(bestslackpos < consdata->nvars);
10074 
10075  /* do not multi aggregate binary variables */
10076  if( SCIPvarIsBinary(vars[bestslackpos]) )
10077  return SCIP_OKAY;
10078 
10079  /* convert equality into inequality by deleting the slack variable:
10080  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
10081  */
10082  slackvar = vars[bestslackpos];
10083  slackcoef = vals[bestslackpos];
10084  assert(!SCIPisZero(scip, slackcoef));
10085  aggrconst = consdata->rhs/slackcoef;
10086 
10087  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
10088  assert(SCIPisLE(scip, newlhs, newrhs));
10089  SCIP_CALL( chgLhs(scip, cons, newlhs) );
10090  SCIP_CALL( chgRhs(scip, cons, newrhs) );
10091  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
10092 
10093  /* allocate temporary memory */
10094  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
10095 
10096  /* set up the multi-aggregation */
10097  SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
10098  for( v = 0; v < consdata->nvars; ++v )
10099  {
10100  scalars[v] = -consdata->vals[v]/slackcoef;
10101  SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
10102  }
10103  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
10104  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
10105  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
10106 
10107  /* perform the multi-aggregation */
10108  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10109  &infeasible, &aggregated) );
10110  assert(aggregated);
10111 
10112  /* free temporary memory */
10113  SCIPfreeBufferArray(scip, &scalars);
10114 
10115  /* check for infeasible aggregation */
10116  if( infeasible )
10117  {
10118  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10119  *cutoff = TRUE;
10120  return SCIP_OKAY;
10121  }
10122 
10123  (*naggrvars)++;
10124 
10125  /* delete the constraint if it became redundant */
10126  if( bestremovescons )
10127  {
10128  SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10129  SCIP_CALL( SCIPdelCons(scip, cons) );
10130 
10131  if( !consdata->upgraded )
10132  (*ndelconss)++;
10133  }
10134  }
10135  else if( ncontvars == 1 )
10136  {
10137  SCIP_VAR* var;
10138 
10139  assert(0 <= contvarpos && contvarpos < consdata->nvars);
10140  var = vars[contvarpos];
10141  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
10142 
10143  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10144  {
10145  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10146  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10147  {
10148  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10149  SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10150  SCIPconsGetName(cons), SCIPvarGetName(var));
10151  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10152  if( infeasible )
10153  {
10154  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10155  *cutoff = TRUE;
10156 
10157  return SCIP_OKAY;
10158  }
10159  }
10160  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10161  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10162  else if( !SCIPdoNotAggr(scip) )
10163  {
10164  SCIP_VAR* newvar;
10165  SCIP_Real absval;
10166  char newvarname[SCIP_MAXSTRLEN];
10167  SCIP_Bool redundant;
10168  SCIP_Bool aggregated;
10169 
10170  absval = REALABS(vals[contvarpos]);
10171 
10172  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10173 
10174  /* create new implicit variable for aggregation */
10175  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10177 
10178  /* add new variable to problem */
10179  SCIP_CALL( SCIPaddVar(scip, newvar) );
10180 
10181 #ifdef WITH_DEBUG_SOLUTION
10182  if( SCIPdebugIsMainscip(scip) )
10183  {
10184  SCIP_Real varval;
10185  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10186  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10187  }
10188 #endif
10189 
10190  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10191  SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10192  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10193 
10194  /* aggregate continuous and implicit variable */
10195  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10196 
10197  if( infeasible )
10198  {
10199  SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10200  SCIPvarGetName(var), SCIPvarGetName(newvar));
10201  *cutoff = TRUE;
10202 
10203  /* release implicit variable */
10204  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10205 
10206  return SCIP_OKAY;
10207  }
10208 
10209  /* release implicit variable */
10210  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10211 
10212  if( aggregated )
10213  (*naggrvars)++;
10214  else
10215  return SCIP_OKAY;
10216  }
10217 
10218  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10219  * again
10220  */
10221  consdata->boundstightened = 0;
10222  consdata->rangedrowpropagated = 0;
10223  consdata->presolved = FALSE;
10224  }
10225  }
10226  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10227  {
10228  SCIP_VAR* var;
10229 
10230  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10231  * -> we don't convert integers into implints if the row is a 0/1-row
10232  */
10233  assert(varsintegral);
10234  assert(0 <= intvarpos && intvarpos < consdata->nvars);
10235  var = vars[intvarpos];
10236  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10237 
10238  if( coefsintegral
10239  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10240  && SCIPisFeasIntegral(scip, consdata->rhs) )
10241  {
10242  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10243  SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10244  SCIPconsGetName(cons), SCIPvarGetName(var));
10245  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10246  if( infeasible )
10247  {
10248  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10249  *cutoff = TRUE;
10250 
10251  return SCIP_OKAY;
10252  }
10253  }
10254  }
10255 
10256  return SCIP_OKAY;
10257 }
10258 
10259 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10260 static
10262  SCIP* scip, /**< SCIP data structure */
10263  SCIP_CONSDATA* consdata, /**< linear constraint data */
10264  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10265  * objective function */
10266  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10267  * this constraint */
10268  )
10269 {
10270  SCIP_VAR** vars;
10271  SCIP_VAR* var;
10272  SCIP_Real objval;
10273  SCIP_Bool negated;
10274  int nvars;
10275  int v;
10276 
10277  vars = consdata->vars;
10278  nvars = consdata->nvars;
10279 
10280  assert(vars != NULL);
10281 
10282  for( v = 0; v < nvars; ++v )
10283  {
10284  negated = FALSE;
10285  var = vars[v];
10286  assert(var != NULL);
10287 
10288  if( SCIPvarIsNegated(var) )
10289  {
10290  negated = TRUE;
10291  var = SCIPvarGetNegatedVar(var);
10292  assert(var != NULL);
10293  }
10294 
10295  objval = SCIPvarGetObj(var);
10296 
10297  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10298  * function
10299  */
10300  if( SCIPisZero(scip, objval) )
10301  return FALSE;
10302  else
10303  {
10304  SCIP_Real val;
10305 
10306  val = consdata->vals[v];
10307 
10308  if( negated )
10309  {
10310  if( v == 0 )
10311  {
10312  /* the first variable defines the scale */
10313  (*scale) = val / -objval;
10314 
10315  (*offset) += val;
10316  }
10317  else if( SCIPisEQ(scip, -objval * (*scale), val) )
10318  (*offset) += val;
10319  else
10320  return FALSE;
10321  }
10322  else if( v == 0 )
10323  {
10324  /* the first variable defines the scale */
10325  (*scale) = val / objval;
10326  }
10327  else if( !SCIPisEQ(scip, objval * (*scale), val) )
10328  return FALSE;
10329  }
10330  }
10331 
10332  return TRUE;
10333 }
10334 
10335 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10336  * objective coefficients and add an objective offset
10337  */
10338 static
10340  SCIP* scip, /**< SCIP data structure */
10341  SCIP_CONS* cons, /**< linear equation constraint */
10342  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10343  )
10344 {
10345  SCIP_CONSDATA* consdata;
10346  SCIP_Real offset;
10347  SCIP_Real scale;
10348  SCIP_Bool applicable;
10349  int nobjvars;
10350  int nvars;
10351  int v;
10352 
10353  assert(scip != NULL);
10354  assert(cons != NULL);
10355  assert(conshdlrdata != NULL);
10356 
10357  consdata = SCIPconsGetData(cons);
10358  assert(consdata != NULL);
10359  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10360 
10361  nvars = consdata->nvars;
10362  nobjvars = SCIPgetNObjVars(scip);
10363 
10364  /* check if the linear equality constraints does not have more variables than the objective function */
10365  if( nvars > nobjvars || nvars == 0 )
10366  return SCIP_OKAY;
10367 
10368  /* check for allowance of algorithm */
10369  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10370  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10371  return SCIP_OKAY;
10372 
10373  offset = consdata->rhs;
10374  scale = 1.0;
10375 
10376  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10377  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10378 
10379  if( applicable )
10380  {
10381  SCIP_VAR** vars;
10382 
10383  vars = consdata->vars;
10384  assert(vars != NULL);
10385 
10386  offset /= scale;
10387 
10388  SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10389  SCIPconsGetName(cons), consdata->rhs, offset);
10390 
10391  /* make equality a model constraint to ensure optimality in this direction */
10392  SCIP_CALL( SCIPsetConsChecked(scip, cons, TRUE) );
10393  SCIP_CALL( SCIPsetConsEnforced(scip, cons, TRUE) );
10394 
10395  /* set all objective coefficient to zero */
10396  for( v = 0; v < nvars; ++v )
10397  {
10398  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10399  }
10400 
10401  /* add an objective offset */
10402  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10403  }
10404 
10405  return SCIP_OKAY;
10406 }
10407 
10408 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10409 static
10411  SCIP* scip, /**< SCIP data structure */
10412  SCIP_CONS* cons, /**< constraint */
10413  SCIP_Real primalbound /**< feasible primal bound */
10414  )
10415 {
10416  SCIP_Real cutoffbound;
10417 
10418  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10419  * accepted
10420  */
10421  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10422 
10423  if( cutoffbound < SCIPgetCutoffbound(scip) )
10424  {
10425  SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10426 
10427  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10428  }
10429  else
10430  {
10431  SCIP_CONSDATA* consdata;
10432 
10433  consdata = SCIPconsGetData(cons);
10434  assert(consdata != NULL);
10435 
10436  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10437  * resulted from one side
10438  */
10439  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10440  {
10441  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10442  * propagation
10443  */
10444  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
10445  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
10446  }
10447  }
10448 
10449  return SCIP_OKAY;
10450 }
10451 
10452 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10453  * constraint enters the LP by setting the initial and separated flag to FALSE
10454  */
10455 static
10457  SCIP* scip, /**< SCIP data structure */
10458  SCIP_CONS* cons, /**< linear constraint */
10459  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10460  )
10461 {
10462  SCIP_CONSDATA* consdata;
10463  SCIP_Real offset;
10464  SCIP_Real scale;
10465  SCIP_Bool applicable;
10466  int nobjvars;
10467  int nvars;
10468 
10469  assert(scip != NULL);
10470  assert(cons != NULL);
10471  assert(conshdlrdata != NULL);
10472 
10473  consdata = SCIPconsGetData(cons);
10474  assert(consdata != NULL);
10476  /* ignore equalities since these are covered by the method checkPartialObjective() */
10477  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10478  return SCIP_OKAY;
10479 
10480  nvars = consdata->nvars;
10481  nobjvars = SCIPgetNObjVars(scip);
10482 
10483  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10484  * initial and/or separated flag is set to FALSE
10485  */
10486  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10487  return SCIP_OKAY;
10488 
10489  offset = 0.0;
10490  scale = 1.0;
10491 
10492  /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10493  * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10494  */
10495  if( nobjvars == 0 )
10496  return SCIP_OKAY;
10497 
10498  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10499  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10500 
10501  if( applicable )
10502  {
10503  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10504  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10505 
10506  assert(scale != 0.0);
10507 
10508  if( scale > 0.0 )
10509  {
10510  if( conshdlrdata->detectcutoffbound && rhsfinite )
10511  {
10512  SCIP_Real primalbound;
10513 
10514  primalbound = (consdata->rhs - offset) / scale;
10515 
10516  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10517  SCIPconsGetName(cons), primalbound);
10518 
10519  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10520  }
10521 
10522  if( conshdlrdata->detectlowerbound && lhsfinite )
10523  {
10524  SCIP_Real lowerbound;
10525 
10526  lowerbound = (consdata->lhs - offset) / scale;
10527 
10528  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10529  SCIPconsGetName(cons), lowerbound);
10530 
10531  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10532  }
10533 
10534  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10535  (conshdlrdata->detectlowerbound && !rhsfinite) )
10536  {
10537  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10538  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10539  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10540  }
10541  }
10542  else
10543  {
10544  if( conshdlrdata->detectlowerbound && rhsfinite )
10545  {
10546  SCIP_Real lowerbound;
10547 
10548  lowerbound = (consdata->rhs - offset) / scale;
10549 
10550  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10551  SCIPconsGetName(cons), lowerbound);
10552 
10553  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10554  }
10555 
10556  if( conshdlrdata->detectcutoffbound && lhsfinite )
10557  {
10558  SCIP_Real primalbound;
10559 
10560  primalbound = (consdata->lhs - offset) / scale;
10561 
10562  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10563  SCIPconsGetName(cons), primalbound);
10564 
10565  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10566  }
10567 
10568  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10569  (conshdlrdata->detectlowerbound && !lhsfinite) )
10570  {
10571  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10572  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10573  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10574  }
10575  }
10576  }
10577 
10578  return SCIP_OKAY;
10579 }
10580 
10581 /** converts special equalities */
10582 static
10584  SCIP* scip, /**< SCIP data structure */
10585  SCIP_CONS* cons, /**< linear constraint */
10586  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10587  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10588  int* nfixedvars, /**< pointer to count number of fixed variables */
10589  int* naggrvars, /**< pointer to count number of aggregated variables */
10590  int* ndelconss /**< pointer to count number of deleted constraints */
10591  )
10592 {
10593  SCIP_CONSDATA* consdata;
10594 
10595  assert(scip != NULL);
10596  assert(cons != NULL);
10597  assert(conshdlrdata != NULL);
10598  assert(cutoff != NULL);
10599  assert(nfixedvars != NULL);
10600  assert(naggrvars != NULL);
10601  assert(ndelconss != NULL);
10603  consdata = SCIPconsGetData(cons);
10604  assert(consdata != NULL);
10605  assert(consdata->removedfixings);
10606 
10607  /* do nothing on inequalities */
10608  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10609  return SCIP_OKAY;
10610 
10611  /* depending on the number of variables, call a special conversion method */
10612  if( consdata->nvars == 1 )
10613  {
10614  /* fix variable */
10615  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10616  }
10617  else if( consdata->nvars == 2 )
10618  {
10619  /* aggregate one of the variables */
10620  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10621  }
10622  else
10623  {
10624  /* check if the equality is part of the objective function */
10625  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10626 
10627  /* try to multi-aggregate one of the variables */
10628  SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10629  }
10630 
10631  return SCIP_OKAY;
10632 }
10633 
10634 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10635  * integral
10636  */
10637 static
10639  SCIP* scip, /**< SCIP data structure */
10640  SCIP_CONSDATA* consdata, /**< linear constraint */
10641  int pos, /**< position of variable to be left out */
10642  SCIP_Real val /**< value to divide the coefficients by */
10643  )
10644 {
10645  int v;
10646 
10647  assert(scip != NULL);
10648  assert(consdata != NULL);
10649  assert(0 <= pos && pos < consdata->nvars);
10650 
10651  for( v = 0; v < consdata->nvars; ++v )
10652  {
10653  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10654  return FALSE;
10655  }
10656 
10657  return TRUE;
10658 }
10659 
10660 /** 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$,
10661  * 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$
10662  */
10663 static
10665  SCIP* scip, /**< SCIP data structure */
10666  SCIP_Real side, /**< lhs or rhs */
10667  SCIP_Real val, /**< coefficient */
10668  SCIP_Real minresactivity, /**< minimal residual activity */
10669  SCIP_Real maxresactivity, /**< maximal residual activity */
10670  SCIP_Real* minval, /**< pointer to store calculated minval */
10671  SCIP_Real* maxval /**< pointer to store calculated maxval */
10672  )
10673 {
10674  assert(scip != NULL);
10675  assert(minval != NULL);
10676  assert(maxval != NULL);
10677 
10678  if( val > 0.0 )
10679  {
10680  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10681  *minval = -maxresactivity;
10682  else
10683  *minval = (side - maxresactivity)/val;
10684 
10685  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10686  *maxval = -minresactivity;
10687  else
10688  *maxval = (side - minresactivity)/val;
10689  }
10690  else
10691  {
10692  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10693  *minval = minresactivity;
10694  else
10695  *minval = (side - minresactivity)/val;
10696 
10697  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10698  *maxval = maxresactivity;
10699  else
10700  *maxval = (side - maxresactivity)/val;
10701  }
10702 }
10703 
10704 
10705 /** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10706  * linear inequality
10707  */
10708 static
10710  SCIP* scip, /**< SCIP data structure */
10711  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10712  SCIP_CONS* cons, /**< linear constraint */
10713  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10714  int* nfixedvars, /**< pointer to count number of fixed variables */
10715  int* naggrvars, /**< pointer to count number of aggregated variables */
10716  int* ndelconss /**< pointer to count number of deleted constraints */
10717  )
10718 {
10719  SCIP_CONSDATA* consdata;
10720  SCIP_Bool lhsexists;
10721  SCIP_Bool rhsexists;
10722  SCIP_Bool bestisint;
10723  SCIP_Bool bestislhs;
10724  SCIP_Real minabsval;
10725  SCIP_Real maxabsval;
10726  int bestpos;
10727  int i;
10728  int maxotherlocks;
10729 
10730  assert(scip != NULL);
10731  assert(cons != NULL);
10732  assert(cutoff != NULL);
10733  assert(nfixedvars != NULL);
10734  assert(naggrvars != NULL);
10735  assert(ndelconss != NULL);
10736 
10737  /* only process checked constraints (for which the locks are increased);
10738  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10739  * dualfix presolver
10740  */
10741  if( !SCIPconsIsChecked(cons) )
10742  return SCIP_OKAY;
10743 
10744  consdata = SCIPconsGetData(cons);
10745  assert(consdata != NULL);
10746 
10747  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10748  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10749 
10750  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10751  * can use it safely for aggregation and break the search loop
10752  */
10753  bestpos = -1;
10754  bestisint = TRUE;
10755  bestislhs = FALSE;
10756 
10757  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10758  * everything else would produce fill-in. Exceptions:
10759  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10760  * produced.
10761  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10762  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10763  * six nonzeros (two variables per substitution).
10764  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10765  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10766  * six nonzeros (three variables per substitution). God exists!
10767  */
10768  if( consdata->nvars <= 2 )
10769  maxotherlocks = INT_MAX;
10770  else if( consdata->nvars == 3 )
10771  maxotherlocks = 3;
10772  else if( consdata->nvars == 4 )
10773  maxotherlocks = 2;
10774  else
10775  maxotherlocks = 1;
10776 
10777  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10778  if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10779  maxotherlocks++;
10780 
10781  minabsval = SCIPinfinity(scip);
10782  maxabsval = -1.0;
10783  for( i = 0; i < consdata->nvars && bestisint; ++i )
10784  {
10785  SCIP_VAR* var;
10786  SCIP_Bool isint;
10787  SCIP_Real val;
10788  SCIP_Real absval;
10789  SCIP_Real obj;
10790  SCIP_Real lb;
10791  SCIP_Real ub;
10792  SCIP_Bool agglhs;
10793  SCIP_Bool aggrhs;
10794 
10795  val = consdata->vals[i];
10796  absval = REALABS(val);
10797 
10798  /* calculate minimal and maximal absolute value */
10799  if( absval < minabsval )
10800  minabsval = absval;
10801  if( absval > maxabsval )
10802  maxabsval = absval;
10803 
10804  /* do not try to multi aggregate, when numerical bad */
10805  if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10806  return SCIP_OKAY;
10807 
10808  var = consdata->vars[i];
10810 
10811  /* if we already found a candidate, skip integers */
10812  if( bestpos >= 0 && isint )
10813  continue;
10814 
10815  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10816  * active, fixed, or single-aggregated with another binary variable
10817  */
10818  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10819  continue;
10820 
10821  if ( SCIPdoNotMultaggrVar(scip, var) )
10822  continue;
10823 
10824  val = consdata->vals[i];
10825  obj = SCIPvarGetObj(var);
10826  lb = SCIPvarGetLbGlobal(var);
10827  ub = SCIPvarGetUbGlobal(var);
10828 
10829  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10830  *
10831  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10832  * - constraint is the only one that forbids fixing the variable to its lower bound
10833  * - 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
10834  *
10835  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10836  * - constraint is the only one that forbids fixing the variable to its upper bound
10837  * - 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
10838  *
10839  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10840  * - constraint is the only one that forbids fixing the variable to its upper bound
10841  * - 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
10842  *
10843  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10844  * - constraint is the only one that forbids fixing the variable to its lower bound
10845  * - 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
10846  *
10847  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10848  * of all x_j
10849  * furthermore: we only want to apply this, if no fill-in will be produced
10850  */
10851  agglhs = lhsexists
10852  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10853  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10854  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10855  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10856  aggrhs = rhsexists
10857  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10858  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10859  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10860  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10861  if( agglhs || aggrhs )
10862  {
10863  SCIP_Real minresactivity;
10864  SCIP_Real maxresactivity;
10865  SCIP_Real minval;
10866  SCIP_Real maxval;
10867  SCIP_Bool ismintight;
10868  SCIP_Bool ismaxtight;
10869  SCIP_Bool isminsettoinfinity;
10870  SCIP_Bool ismaxsettoinfinity;
10871 
10872  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10873  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10874  &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
10875  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10876 
10877  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10878  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10879  * This is needed, because we do not want to rely on relaxed finite resactivities.
10880  */
10881  assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
10882 
10883  if( agglhs )
10884  {
10885  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10886  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10887 
10888  assert(SCIPisLE(scip, minval, maxval));
10889  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10890  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10891  {
10892  SCIP_Real oldmaxresactivity;
10893  SCIP_Real oldminresactivity;
10894  SCIP_Bool recalculated;
10895 
10896  recalculated = FALSE;
10897  oldmaxresactivity = maxresactivity;
10898  oldminresactivity = minresactivity;
10899 
10900  /* check minresactivity for reliability */
10901  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10902  {
10903  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10904  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10905  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10906  }
10907 
10908  /* check maxresactivity for reliability */
10909  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10910  {
10911  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10912  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10913  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10914  }
10915 
10916  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10917  if( recalculated )
10918  {
10919  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10920 
10921  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10922  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10923 
10924  assert(SCIPisLE(scip, minval, maxval));
10925  }
10926 
10927  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10928  {
10929  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10930  * in the multi-aggregation
10931  */
10932  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10933  {
10934  bestpos = i;
10935  bestisint = isint;
10936  bestislhs = TRUE;
10937  continue; /* no need to also look at the right hand side */
10938  }
10939  }
10940  }
10941  }
10942 
10943  if( aggrhs )
10944  {
10945  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10946  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10947 
10948  assert(SCIPisLE(scip,minval,maxval));
10949  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10950  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10951  {
10952  SCIP_Real oldmaxresactivity;
10953  SCIP_Real oldminresactivity;
10954  SCIP_Bool recalculated;
10955 
10956  recalculated = FALSE;
10957  oldmaxresactivity = maxresactivity;
10958  oldminresactivity = minresactivity;
10959 
10960  /* check minresactivity for reliability */
10961  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10962  {
10963  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10964  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10965  }
10966 
10967  /* check maxresactivity for reliability */
10968  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10969  {
10970  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10971  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10972  }
10973 
10974  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10975  if( recalculated )
10976  {
10977  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10978  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10979  assert(SCIPisLE(scip,minval,maxval));
10980  }
10981 
10982  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10983  {
10984  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10985  * in the multi-aggregation
10986  */
10987  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10988  {
10989  bestpos = i;
10990  bestisint = isint;
10991  bestislhs = FALSE;
10992  }
10993  }
10994  }
10995  }
10996  }
10997  }
10998 
10999  if( bestpos >= 0 )
11000  {
11001  SCIP_VAR** aggrvars;
11002  SCIP_Real* aggrcoefs;
11003  SCIP_Real aggrconst;
11004  SCIP_VAR* bestvar;
11005  SCIP_Real bestval;
11006  SCIP_Real epsilon;
11007  int naggrs;
11008  int j;
11009  SCIP_Bool infeasible;
11010  SCIP_Bool aggregated;
11011  SCIP_Bool samevar;
11012  int supinf; /* counter for infinite contributions to the supremum of a possible
11013  * multi-aggregation
11014  */
11015  int infinf; /* counter for infinite contributions to the infimum of a possible
11016  * multi-aggregation
11017  */
11018 
11019  assert(!bestislhs || lhsexists);
11020  assert(bestislhs || rhsexists);
11021 
11022  bestvar = consdata->vars[bestpos];
11023  bestval = consdata->vals[bestpos];
11024  assert(bestisint ==
11026 
11027  /* allocate temporary memory */
11028  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
11029  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
11030 
11031  /* set up the multi-aggregation */
11032  SCIPdebugPrintCons(scip, cons, NULL);
11033  SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
11034  naggrs = 0;
11035  supinf = 0;
11036  infinf = 0;
11037  samevar = FALSE;
11038  epsilon = SCIPepsilon(scip);
11039 
11040  for( j = 0; j < consdata->nvars; ++j )
11041  {
11042  if( j != bestpos )
11043  {
11044  SCIP_Real absaggrcoef;
11045 
11046  aggrvars[naggrs] = consdata->vars[j];
11047  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
11048  SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
11049 
11050  absaggrcoef = REALABS(aggrcoefs[naggrs]);
11051 
11052  /* do not try to multi aggregate, when numerical bad */
11053  if( absaggrcoef < epsilon )
11054  {
11055  SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
11056 
11057  /* free temporary memory */
11058  SCIPfreeBufferArray(scip, &aggrcoefs);
11059  SCIPfreeBufferArray(scip, &aggrvars);
11060 
11061  return SCIP_OKAY;
11062  }
11063 
11064  if( bestisint )
11065  {
11066  /* coefficient must be integral: round it to exact integral value */
11067  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
11068  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
11069  }
11070 
11071  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
11072  {
11073  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11074  {
11075  ++supinf;
11076  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11077  {
11078  ++infinf;
11079  samevar = TRUE;
11080  }
11081  }
11082  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11083  ++infinf;
11084  }
11085  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
11086  {
11087  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11088  {
11089  ++supinf;
11090  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11091  {
11092  ++infinf;
11093  samevar = TRUE;
11094  }
11095  }
11096  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11097  ++infinf;
11098  }
11099 
11100  naggrs++;
11101  }
11102  }
11103  assert(!samevar || (supinf > 0 && infinf > 0));
11104 
11105  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11106  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11107  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
11108  assert(naggrs == consdata->nvars-1);
11109 
11110  /* right hand side must be integral: round it to exact integral value */
11111  if( bestisint )
11112  {
11113  assert(SCIPisIntegral(scip, aggrconst));
11114  aggrconst = SCIPfloor(scip, aggrconst+0.5);
11115  }
11116 
11117  aggregated = FALSE;
11118  infeasible = FALSE;
11119 
11120  /* perform the multi-aggregation */
11121  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11122  {
11123  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11124  * also convertLongEquality() early termination due to coefficients
11125  */
11126  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11127 
11128  /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11129  * the implicitness might rely on the constraint and the integrality of bestvar
11130  */
11131  if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11132  {
11133  SCIP_Bool infeasiblevartypechg;
11134 
11135  for( j = 0; j < naggrs; ++j)
11136  {
11137  /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11138  * lead to infeasibility
11139  */
11140  if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT )
11141  {
11142  SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
11143  assert(!infeasiblevartypechg);
11144  }
11145  }
11146  }
11147  }
11148  else
11149  {
11150  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11151  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11152  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11153  }
11154  /* free temporary memory */
11155  SCIPfreeBufferArray(scip, &aggrcoefs);
11156  SCIPfreeBufferArray(scip, &aggrvars);
11157 
11158  /* check for infeasible aggregation */
11159  if( infeasible )
11160  {
11161  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11162  *cutoff = TRUE;
11163  return SCIP_OKAY;
11164  }
11165 
11166  /* delete the constraint, if the aggregation was successful */
11167  if( aggregated )
11168  {
11169  SCIP_CALL( SCIPdelCons(scip, cons) );
11170 
11171  if( !consdata->upgraded )
11172  (*ndelconss)++;
11173  (*naggrvars)++;
11174  }
11175  else
11176  {
11177  SCIPdebugMsg(scip, "aggregation non successful!\n");
11178  }
11179  }
11180 
11181  return SCIP_OKAY;
11182 }
11183 
11184 #define BINWEIGHT 1
11185 #define INTWEIGHT 4
11186 #define CONTWEIGHT 8
11187 
11188 /** gets weight for variable in a "weighted number of variables" sum */
11189 static
11190 int getVarWeight(
11191  SCIP_VAR* var /**< variable to get weight for */
11192  )
11193 {
11194  switch( SCIPvarGetType(var) )
11195  {
11196  case SCIP_VARTYPE_BINARY:
11197  return BINWEIGHT;
11198  case SCIP_VARTYPE_INTEGER:
11199  case SCIP_VARTYPE_IMPLINT:
11200  return INTWEIGHT;
11202  return CONTWEIGHT;
11203  default:
11204  SCIPerrorMessage("invalid variable type\n");
11206  return 0; /*lint !e527*/
11207  }
11208 }
11210 /** tries to aggregate variables in equations a^Tx = lhs
11211  * in case there are at most two binary variables with an odd coefficient and all other
11212  * variables are not continuous and have an even coefficient then:
11213  * - exactly one odd binary variables
11214  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11215  * - lhs is odd -> y = 1
11216  * - lhs is even -> y = 0
11217  * - exactly two odd binary variables
11218  * aggregate the two binary variables with odd coefficient
11219  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11220  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11221  */
11222 static
11224  SCIP* scip, /**< SCIP data structure */
11225  SCIP_CONS* cons, /**< linear constraint */
11226  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11227  int* nfixedvars, /**< pointer to count number of fixed variables */
11228  int* naggrvars /**< pointer to count number of aggregated variables */
11229  )
11230 { /*lint --e{715}*/
11231  SCIP_CONSDATA* consdata;
11232  SCIP_Bool success;
11233 
11234  assert( scip != NULL );
11235  assert( cons != NULL );
11236 
11237  consdata = SCIPconsGetData(cons);
11238  assert( consdata != NULL );
11239 
11240  /* check if the linear constraint is an equation with integral right hand side */
11241  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11242  return SCIP_OKAY;
11243 
11244  /* try to fix and aggregated variables until nothing is possible anymore */
11245  do
11246  {
11247  int v;
11248  int nvars;
11249  SCIP_VAR** vars;
11250  SCIP_Real* vals;
11251  SCIP_Real lhs;
11252  SCIP_Bool lhsodd;
11253 
11254  SCIP_Bool infeasible;
11255  SCIP_Bool fixed;
11256  SCIP_Bool aggregated;
11257  SCIP_Bool redundant;
11258 
11259  SCIP_VAR* var1;
11260  SCIP_VAR* var2;
11261  int noddvars;
11262 
11263  success = FALSE;
11264 
11265  lhs = consdata->lhs;
11266  vars = consdata->vars;
11267  vals = consdata->vals;
11268  nvars = consdata->nvars;
11269 
11270  assert( !SCIPisInfinity(scip, ABS(lhs)) );
11271 
11272  var1 = NULL;
11273  var2 = NULL;
11274  noddvars = 0;
11275 
11276  /* search for binary variables with an odd coefficient */
11277  for( v = 0; v < nvars && noddvars < 3; ++v )
11278  {
11279  SCIP_Longint val;
11280 
11281  /* all coefficients and variables have to be integral */
11282  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11283  return SCIP_OKAY;
11284 
11285  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11286  if( val % 2 != 0 )
11287  {
11288  /* the odd values have to belong to binary variables */
11289  if( !SCIPvarIsBinary(vars[v]) )
11290  return SCIP_OKAY;
11291 
11292  if( noddvars == 0 )
11293  var1 = vars[v];
11294  else
11295  var2 = vars[v];
11296 
11297  noddvars++;
11298  }
11299  }
11300 
11301  /* check lhs is odd or even */
11302  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11303 
11304  if( noddvars == 1 )
11305  {
11306  assert( var1 != NULL );
11307 
11308  SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11309  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11310 
11311  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11312 
11313  /* check for infeasibility of fixing */
11314  if( infeasible )
11315  {
11316  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11317  *cutoff = TRUE;
11318  return SCIP_OKAY;
11319  }
11320 
11321  if( fixed )
11322  {
11323  SCIPdebugMsg(scip, " -> feasible fixing\n");
11324  (*nfixedvars)++;
11325  success = TRUE;
11326  }
11327  }
11328  else if( noddvars == 2 )
11329  {
11330  assert( var1 != NULL );
11331  assert( var2 != NULL );
11332 
11333  /* aggregate the two variables with odd coefficient
11334  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11335  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11336  */
11337  SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11338  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11339 
11340  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11341  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11342 
11343  /* check for infeasibility of aggregation */
11344  if( infeasible )
11345  {
11346  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11347  *cutoff = TRUE;
11348  return SCIP_OKAY;
11349  }
11350 
11351  /* count the aggregation */
11352  if( aggregated )
11353  {
11354  SCIPdebugMsg(scip, " -> feasible aggregation\n");
11355  (*naggrvars)++;
11356  success = TRUE;
11357  }
11358  }
11359 
11360  if( success )
11361  {
11362  /* apply fixings and aggregation to successfully rerun this presolving step */
11363  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11364 
11365  if( infeasible )
11366  {
11367  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11368  *cutoff = TRUE;
11369  return SCIP_OKAY;
11370  }
11371 
11372  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11373 
11374  if( infeasible )
11375  {
11376  SCIPdebugMsg(scip, " -> infeasible normalization\n");
11377  *cutoff = TRUE;
11378  return SCIP_OKAY;
11379  }
11380  }
11381  }
11382  while( success && consdata->nvars >= 1 );
11383 
11384  return SCIP_OKAY;
11385 }
11386 
11387 
11388 
11389 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11390  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11391  * coefficients
11392  */
11393 static
11394 SCIP_DECL_SORTINDCOMP(consdataCompSim)
11395 { /*lint --e{715}*/
11396  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11397  SCIP_VARTYPE vartype1;
11398  SCIP_VARTYPE vartype2;
11399  SCIP_Real value;
11400 
11401  assert(consdata != NULL);
11402  assert(0 <= ind1 && ind1 < consdata->nvars);
11403  assert(0 <= ind2 && ind2 < consdata->nvars);
11404 
11405  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11406  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11407 
11408  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11409  {
11410  /* continuous varibles will be sorted to the back */
11411  if( vartype2 != vartype1 )
11412  return +1;
11413  /* both variables are continuous */
11414  else
11415  return 0;
11416  }
11417  /* continuous variables will be sorted to the back */
11418  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11419  return -1;
11420 
11421  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11422 
11423  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11424  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11425 }
11426 
11427 /** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11428  *
11429  * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11430  * then we can change this constraint to 1^Tx = 1
11431  */
11432 static
11434  SCIP* scip, /**< SCIP data structure */
11435  SCIP_CONS* cons, /**< linear constraint */
11436  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11437  int* nchgsides /**< pointer to store the amount of changed sides */
11438  )
11439 {
11440  SCIP_CONSDATA* consdata;
11441  SCIP_VAR** vars;
11442  SCIP_Real* vals;
11443  SCIP_Real minval;
11444  SCIP_Real secondminval;
11445  SCIP_Real maxval;
11446  SCIP_Real lhs;
11447  SCIP_Real rhs;
11448  int nvars;
11449  int v;
11450 
11451  /* we must not change a modifiable constraint in any way */
11453  return SCIP_OKAY;
11454 
11455  if( SCIPconsIsDeleted(cons) )
11456  return SCIP_OKAY;
11457 
11458  consdata = SCIPconsGetData(cons);
11459  assert(consdata != NULL);
11460 
11461  nvars = consdata->nvars;
11462 
11463  /* do not check empty or bound-constraints */
11464  if( nvars < 2 )
11465  return SCIP_OKAY;
11466 
11467  lhs = consdata->lhs;
11468  rhs = consdata->rhs;
11469  assert(!SCIPisInfinity(scip, -lhs));
11470  assert(!SCIPisInfinity(scip, rhs));
11471  assert(!SCIPisNegative(scip, rhs));
11472 
11473  /* sides must be positive and different to detect set partition */
11474  if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11475  return SCIP_OKAY;
11476 
11477  vals = consdata->vals;
11478  vars = consdata->vars;
11479  assert(vars != NULL);
11480  assert(vals != NULL);
11481 
11482  minval = SCIP_INVALID;
11483  secondminval = SCIP_INVALID;
11484  maxval = -SCIP_INVALID;
11485 
11486  for( v = nvars - 1; v >= 0; --v )
11487  {
11488  if( SCIPvarIsBinary(vars[v]) )
11489  {
11490  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11491  {
11492  secondminval = minval;
11493  minval = vals[v];
11494  }
11495  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11496  secondminval = vals[v];
11497 
11498  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11499  maxval = vals[v];
11500  }
11501  else
11502  break;
11503  }
11504 
11505  /* check if all variables are binary, we can choose one, and need to choose at most one */
11506  if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11507  && SCIPisGT(scip, minval + secondminval, rhs) )
11508  {
11509  /* change all coefficients to 1.0 */
11510  for( v = nvars - 1; v >= 0; --v )
11511  {
11512  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11513  }
11514  (*nchgcoefs) += nvars;
11515 
11516  /* replace old right and left hand side with 1.0 */
11517  SCIP_CALL( chgRhs(scip, cons, 1.0) );
11518  SCIP_CALL( chgLhs(scip, cons, 1.0) );
11519  (*nchgsides) += 2;
11520  }
11521 
11522  return SCIP_OKAY;
11523 }
11524 
11525 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11526  *
11527  * for both-sided constraints only @see rangedRowSimplify() will be called
11528  *
11529  * for one-sided constraints there are several different coefficient reduction steps which will be applied
11530  *
11531  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11532  *
11533  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11534  *
11535  * 2. We try to remove redundant fractional parts in a constraint
11536  *
11537  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11538  *
11539  * 3. We are using the greatest common divisor for further reductions
11540  *
11541  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11542  * integral
11543  */
11544 static
11546  SCIP* scip, /**< SCIP data structure */
11547  SCIP_CONS* cons, /**< linear constraint */
11548  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11549  int* nchgsides, /**< pointer to store the amount of changed sides */
11550  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11551  )
11552 {
11553  SCIP_CONSDATA* consdata;
11554  SCIP_VAR** vars;
11555  SCIP_Real* vals;
11556  int* perm;
11557  SCIP_Real minactsub;
11558  SCIP_Real maxactsub;
11559  SCIP_Real siderest;
11560  SCIP_Real feastol;
11561  SCIP_Real newcoef;
11562  SCIP_Real absval;
11563  SCIP_Real minact;
11564  SCIP_Real maxact;
11565  SCIP_Real side;
11566  SCIP_Real lhs;
11567  SCIP_Real rhs;
11568  SCIP_Real lb;
11569  SCIP_Real ub;
11570  SCIP_Longint restcoef;
11571  SCIP_Longint oldgcd;
11572  SCIP_Longint rest;
11573  SCIP_Longint gcd;
11574  SCIP_Bool isminsettoinfinity;
11575  SCIP_Bool ismaxsettoinfinity;
11576  SCIP_Bool ismintight;
11577  SCIP_Bool ismaxtight;
11578  SCIP_Bool allcoefintegral;
11579  SCIP_Bool onlybin;
11580  SCIP_Bool hasrhs;
11581  SCIP_Bool haslhs;
11582  int oldnchgcoefs;
11583  int oldnchgsides;
11584  int foundbin;
11585  int candpos;
11586  int candpos2;
11587  int offsetv;
11588  int nvars;
11589  int v;
11590  int w;
11591 
11592  assert(scip != NULL);
11593  assert(cons != NULL);
11594  assert(nchgcoefs != NULL);
11595  assert(nchgsides != NULL);
11596 
11597  *infeasible = FALSE;
11598 
11599  /* we must not change a modifiable constraint in any way */
11600  if( SCIPconsIsModifiable(cons) )
11601  return SCIP_OKAY;
11602 
11603  if( SCIPconsIsDeleted(cons) )
11604  return SCIP_OKAY;
11605 
11606  consdata = SCIPconsGetData(cons);
11607  assert(consdata != NULL);
11608 
11609  nvars = consdata->nvars;
11610 
11611  /* do not check empty or bound-constraints */
11612  if( nvars <= 2 )
11613  return SCIP_OKAY;
11614 
11615  /* update maximal activity delta if necessary */
11616  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11617  consdataRecomputeMaxActivityDelta(scip, consdata);
11618 
11619  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11620  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11621  checkMaxActivityDelta(scip, consdata);
11622 
11623  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11624  * accordingly
11625  */
11626  /* can only work with valid non-infinity activities per variable */
11627  if( SCIPisInfinity(scip, consdata->maxactdelta) )
11628  return SCIP_OKAY;
11629 
11630  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11631  * but the eventsystem seems to be full
11632  */
11633  consdata->normalized = FALSE;
11634 
11635  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11636  assert(nvars == consdata->nvars);
11637 
11638  if( *infeasible )
11639  return SCIP_OKAY;
11640 
11641  if( !consdata->normalized )
11642  return SCIP_OKAY;
11643 
11644  lhs = consdata->lhs;
11645  rhs = consdata->rhs;
11646  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11647  assert(!SCIPisNegative(scip, rhs));
11648 
11649  if( !SCIPisInfinity(scip, -lhs) )
11650  haslhs = TRUE;
11651  else
11652  haslhs = FALSE;
11653 
11654  if( !SCIPisInfinity(scip, rhs) )
11655  hasrhs = TRUE;
11656  else
11657  hasrhs = FALSE;
11658 
11659  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11660  SCIPdebug( oldnchgsides = *nchgsides; )
11661 
11662  /* @todo extend both-sided simplification */
11663  if( haslhs && hasrhs )
11664  {
11665  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11666 
11667  return SCIP_OKAY;
11668  }
11669  assert(haslhs != hasrhs);
11670 
11671  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11672  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11673  assert(!haslhs || !SCIPisNegative(scip, lhs));
11674 
11675  /* get temporary memory to store the sorted permutation */
11676  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11677 
11678  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11679  * value of their coefficients
11680  */
11681  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11682 
11683  /* perform sorting after permutation array */
11684  permSortConsdata(consdata, perm, nvars);
11685  consdata->indexsorted = FALSE;
11686  consdata->coefsorted = FALSE;
11687 
11688  vars = consdata->vars;
11689  vals = consdata->vals;
11690  assert(vars != NULL);
11691  assert(vals != NULL);
11692  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11693 
11694  /* free temporary memory */
11695  SCIPfreeBufferArray(scip, &perm);
11696 
11697  /* only check constraints with at least two non continuous variables */
11698  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11699  return SCIP_OKAY;
11700 
11701  /* do not process constraints when all coefficients are 1.0 */
11702  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11703  return SCIP_OKAY;
11704 
11705  feastol = SCIPfeastol(scip);
11706 
11707  SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11708  SCIPdebugPrintCons(scip, cons, NULL);
11709 
11710  /* get global activities */
11711  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11712  &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
11713 
11714  /* cannot work with infinite activities */
11715  if( isminsettoinfinity || ismaxsettoinfinity )
11716  return SCIP_OKAY;
11717 
11718  assert(ismintight);
11719  assert(ismaxtight);
11720  assert(maxact > minact);
11721  assert(!SCIPisInfinity(scip, -minact));
11722  assert(!SCIPisInfinity(scip, maxact));
11723 
11724  v = 0;
11725  offsetv = -1;
11726  side = haslhs ? lhs : rhs;
11727  minactsub = minact;
11728  maxactsub = maxact;
11729 
11730  /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11731  * do not need to look at the large coefficients
11732  *
11733  * e.g. all x are binary, z are positive integer
11734  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11735  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11736  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11737  *
11738  * can be changed to
11739  *
11740  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11741  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11742  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11743  */
11744 
11745  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11746  * hand side, we cannot apply the extra reduction step and need to reset v
11747  *
11748  * 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
11749  * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11750  * for all i is a solution
11751  *
11752  * also redundancy of variables would not be correctly determined in such a case
11753  */
11754  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11755  {
11756  v = 1;
11757 
11758  while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11759  {
11760  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11761  * extra step, which might have worked
11762  */
11763  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11764  {
11765  v = 0;
11766  break;
11767  }
11768 
11769  ++v;
11770  }
11771 
11772  /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11773  /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11774  if( v == nvars )
11775  return SCIP_OKAY;
11776 
11777  /* cannot work with continuous variables which have a big coefficient */
11778  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11779  return SCIP_OKAY;
11780 
11781  /* big negative coefficient, do not try to use the extra coefficient reduction step */
11782  if( SCIPisEQ(scip, side, -vals[v]) )
11783  v = 0;
11784 
11785  /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11786  * reduction
11787  */
11788  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11789  v = 0;
11790 
11791  if( v > 0 )
11792  {
11793  assert(v < nvars);
11794 
11795  offsetv = v - 1;
11796 
11797  for( w = 0; w < v; ++w )
11798  {
11799  lb = SCIPvarGetLbGlobal(vars[w]);
11800  ub = SCIPvarGetUbGlobal(vars[w]);
11801 
11802  assert(vals[w] > 0);
11803 
11804  /* update residual activities */
11805  maxactsub -= ub * vals[w];
11806  minactsub -= lb * vals[w];
11807  assert(maxactsub > minactsub);
11808  }
11809  }
11810  }
11811 
11812  /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11813  *
11814  * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11815  *
11816  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11817  * to
11818  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11819  */
11820  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11821  {
11822  SCIP_Bool redundant = FALSE;
11823  SCIP_Bool numericsok;
11824  SCIP_Bool rredundant;
11825  SCIP_Bool lredundant;
11826 
11827  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11828  assert(gcd >= 1);
11829 
11830  if( v == 0 )
11831  {
11832  lb = SCIPvarGetLbGlobal(vars[0]);
11833  ub = SCIPvarGetUbGlobal(vars[0]);
11834 
11835  /* update residual activities */
11836  if( vals[0] > 0 )
11837  {
11838  maxactsub -= ub * vals[0];
11839  minactsub -= lb * vals[0];
11840  }
11841  else
11842  {
11843  maxactsub -= lb * vals[0];
11844  minactsub -= ub * vals[0];
11845  }
11846  assert(maxactsub > minactsub);
11847  ++v;
11848  }
11849 
11850  siderest = -SCIP_INVALID;
11851  allcoefintegral = TRUE;
11852 
11853  /* check if some variables always fit into the given constraint */
11854  for( ; v < nvars - 1; ++v )
11855  {
11856  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11857  break;
11858 
11859  if( !SCIPisIntegral(scip, vals[v]) )
11860  {
11861  allcoefintegral = FALSE;
11862  break;
11863  }
11864 
11865  /* calculate greatest common divisor for all general and binary variables */
11866  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11867 
11868  if( gcd == 1 )
11869  break;
11870 
11871  lb = SCIPvarGetLbGlobal(vars[v]);
11872  ub = SCIPvarGetUbGlobal(vars[v]);
11873 
11874  assert(!SCIPisInfinity(scip, -lb));
11875  assert(!SCIPisInfinity(scip, ub));
11876 
11877  /* update residual activities */
11878  if( vals[v] > 0 )
11879  {
11880  maxactsub -= ub * vals[v];
11881  minactsub -= lb * vals[v];
11882  }
11883  else
11884  {
11885  maxactsub -= lb * vals[v];
11886  minactsub -= ub * vals[v];
11887  }
11888  assert(SCIPisGE(scip, maxactsub, minactsub));
11889 
11890  if( hasrhs )
11891  {
11892  /* determine the remainder of the right hand side and the gcd */
11893  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11894  }
11895  else
11896  {
11897  /* determine the remainder of the left hand side and the gcd */
11898  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11899  if( SCIPisZero(scip, siderest) )
11900  siderest = gcd;
11901  }
11902 
11903  rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11904  lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11905 
11906  /* early termination if the activities deceed the gcd */
11907  if( offsetv == -1 && (rredundant || lredundant) )
11908  {
11909  redundant = TRUE;
11910  break;
11911  }
11912  }
11913  assert(v < nvars || (offsetv >= 0 && gcd > 1));
11914 
11915  if( !redundant )
11916  {
11917  if( hasrhs )
11918  {
11919  /* determine the remainder of the right hand side and the gcd */
11920  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11921  }
11922  else
11923  {
11924  /* determine the remainder of the left hand side and the gcd */
11925  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11926  if( SCIPisZero(scip, siderest) )
11927  siderest = gcd;
11928  }
11929  }
11930  else
11931  ++v;
11932 
11933  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",
11934  v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11935 
11936  /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11937  * reasonable absolute values */
11938  numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11939  REALABS(minactsub) < MAXACTVAL;
11940 
11941  rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11942  lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11943 
11944  /* check if we can remove redundant variables */
11945  if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11946  {
11947  SCIP_Real oldcoef;
11948 
11949  /* double check the redundancy */
11950 #ifndef NDEBUG
11951  SCIP_Real tmpminactsub = 0.0;
11952  SCIP_Real tmpmaxactsub = 0.0;
11953 
11954  /* recompute residual activities */
11955  for( w = v; w < nvars; ++w )
11956  {
11957  lb = SCIPvarGetLbGlobal(vars[w]);
11958  ub = SCIPvarGetUbGlobal(vars[w]);
11959 
11960  assert(!SCIPisInfinity(scip, -lb));
11961  assert(!SCIPisInfinity(scip, ub));
11962 
11963  /* update residual activities */
11964  if( vals[w] > 0 )
11965  {
11966  tmpmaxactsub += ub * vals[w];
11967  tmpminactsub += lb * vals[w];
11968  }
11969  else
11970  {
11971  tmpmaxactsub += lb * vals[w];
11972  tmpminactsub += ub * vals[w];
11973  }
11974  assert(tmpmaxactsub >= tmpminactsub);
11975  }
11976 
11977  if( hasrhs )
11978  {
11979  assert(offsetv == -1);
11980 
11981  /* determine the remainder of the right hand side and the gcd */
11982  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11983  }
11984  else
11985  {
11986  /* determine the remainder of the left hand side and the gcd */
11987  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11988  if( SCIPisZero(scip, siderest) )
11989  siderest = gcd;
11990  }
11991 
11992  /* is the redundancy really fulfilled */
11993  assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11994  (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11995 #endif
11996 
11997  SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11998  nvars - v, SCIPconsGetName(cons));
11999 
12000  /* remove redundant variables */
12001  for( w = nvars - 1; w >= v; --w )
12002  {
12003  SCIP_CALL( delCoefPos(scip, cons, w) );
12004  }
12005  (*nchgcoefs) += (nvars - v);
12006 
12007  assert(w >= 0);
12008 
12009  oldcoef = vals[w];
12010 
12011  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12012  assert(vars == consdata->vars);
12013  assert(vals == consdata->vals);
12014  assert(w < consdata->nvars);
12015 
12016  if( *infeasible )
12017  return SCIP_OKAY;
12018 
12019  /* compute new greatest common divisor due to normalization */
12020  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
12021  assert(gcd >= 1);
12022 
12023  /* update side */
12024  if( hasrhs )
12025  {
12026  /* replace old with new right hand side */
12027  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
12028  rhs = consdata->rhs;
12029  }
12030  else
12031  {
12032  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
12033  {
12034  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
12035  lhs = consdata->lhs;
12036  }
12037  else
12038  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
12039  }
12040  ++(*nchgsides);
12041 
12042  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12043  assert(!haslhs || !SCIPisNegative(scip, lhs));
12044 
12045  /* get new constraint data */
12046  nvars = consdata->nvars;
12047  assert(nvars > 0);
12048 
12049  allcoefintegral = TRUE;
12050 
12051 #ifndef NDEBUG
12052  /* check integrality */
12053  for( w = offsetv + 1; w < nvars; ++w )
12054  {
12055  assert(SCIPisIntegral(scip, vals[w]));
12056  }
12057 #endif
12058  SCIPdebugPrintCons(scip, cons, NULL);
12059  }
12060 
12061  /* try to find a better gcd, when having large coefficients */
12062  if( offsetv >= 0 && gcd == 1 )
12063  {
12064  /* calculate greatest common divisor for all general variables */
12065  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
12066 
12067  if( gcd > 1 )
12068  {
12069  gcd = -1;
12070  candpos = -1;
12071 
12072  for( v = nvars - 1; v > offsetv; --v )
12073  {
12074  assert(!SCIPisZero(scip, vals[v]));
12075  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
12076  break;
12077 
12078  if( !SCIPisIntegral(scip, vals[v]) )
12079  {
12080  allcoefintegral = FALSE;
12081  break;
12082  }
12083 
12084  oldgcd = gcd;
12085 
12086  if( gcd == -1 )
12087  {
12088  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12089  assert(gcd >= 1);
12090  }
12091  else
12092  {
12093  /* calculate greatest common divisor for all general and binary variables */
12094  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12095  }
12096 
12097  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12098  * can stop searching
12099  */
12100  if( gcd == 1 )
12101  {
12102  if( !SCIPvarIsBinary(vars[v]) )
12103  break;
12104 
12105  /* found candidate */
12106  if( candpos == -1 )
12107  {
12108  gcd = oldgcd;
12109  candpos = v;
12110  }
12111  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12112  else
12113  break;
12114  }
12115  }
12116  assert(v > offsetv || candpos > offsetv);
12117  }
12118  else
12119  candpos = -1;
12120  }
12121  else
12122  candpos = nvars - 1;
12123 
12124  /* check last coefficient for integrality */
12125  if( gcd > 1 && allcoefintegral && !redundant )
12126  {
12127  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12128  allcoefintegral = FALSE;
12129  }
12130 
12131  /* check for further necessary coefficient adjustments */
12132  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12133  {
12134  assert(offsetv + 1 < nvars);
12135  assert(0 <= candpos && candpos < nvars);
12136 
12137  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12138  {
12139  SCIP_Bool notchangable = FALSE;
12140 
12141 #ifndef NDEBUG
12142  /* check integrality */
12143  for( w = offsetv + 1; w < nvars; ++w )
12144  {
12145  assert(SCIPisIntegral(scip, vals[w]));
12146  }
12147 #endif
12148 
12149  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12150  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12151  {
12152  /* determine the remainder of the side and the gcd */
12153  if( hasrhs )
12154  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12155  else
12156  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12157  assert(rest >= 0);
12158  assert(rest < gcd);
12159 
12160  /* determine the remainder of the coefficient candidate and the gcd */
12161  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12162  assert(restcoef >= 1);
12163  assert(restcoef < gcd);
12164 
12165  if( hasrhs )
12166  {
12167  /* calculate new coefficient */
12168  if( restcoef > rest )
12169  newcoef = vals[candpos] - restcoef + gcd;
12170  else
12171  newcoef = vals[candpos] - restcoef;
12172  }
12173  else
12174  {
12175  /* calculate new coefficient */
12176  if( rest == 0 || restcoef < rest )
12177  newcoef = vals[candpos] - restcoef;
12178  else
12179  newcoef = vals[candpos] - restcoef + gcd;
12180  }
12181 
12182  /* done */
12183 
12184  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12185  * another with the big coefficient was set to 1
12186  */
12187  if( hasrhs && SCIPisZero(scip, newcoef) )
12188  {
12189  notchangable = TRUE;
12190  }
12191  else if( SCIPisZero(scip, newcoef) )
12192  {
12193  /* delete old redundant coefficient */
12194  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12195  ++(*nchgcoefs);
12196  }
12197  else
12198  {
12199  /* replace old with new coefficient */
12200  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12201  ++(*nchgcoefs);
12202  }
12203  }
12204  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12205  {
12206  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12207  }
12208 
12209  /* correct side and big coefficients */
12210  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12211  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12212  {
12213  if( haslhs )
12214  {
12215  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12216 
12217  SCIP_CALL( chgLhs(scip, cons, newcoef) );
12218  ++(*nchgsides);
12219  }
12220  else
12221  {
12222  assert(hasrhs);
12223  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12224 
12225  SCIP_CALL( chgRhs(scip, cons, newcoef) );
12226  ++(*nchgsides);
12227  }
12228 
12229  /* correct coefficients up front */
12230  for( w = offsetv; w >= 0; --w )
12231  {
12232  assert(vals[w] > 0);
12233 
12234  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12235  }
12236  (*nchgcoefs) += (offsetv + 1);
12237  }
12238 
12239  if( !notchangable )
12240  {
12241  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12242  assert(vars == consdata->vars);
12243  assert(vals == consdata->vals);
12244 
12245  if( *infeasible )
12246  return SCIP_OKAY;
12247 
12248  /* get new constraint data */
12249  nvars = consdata->nvars;
12250  assert(nvars >= 2);
12251 
12252  SCIPdebugPrintCons(scip, cons, NULL);
12253 
12254  lhs = consdata->lhs;
12255  rhs = consdata->rhs;
12256  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12257  assert(!haslhs || !SCIPisNegative(scip, lhs));
12258  }
12259  }
12260  }
12261  }
12262 
12263  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12264  /* no continuous variables are left over */
12265  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12266  return SCIP_OKAY;
12267 
12268  onlybin = TRUE;
12269  allcoefintegral = TRUE;
12270  /* check if all variables are of binary type */
12271  for( v = nvars - 1; v >= 0; --v )
12272  {
12273  if( !SCIPvarIsBinary(vars[v]) )
12274  onlybin = FALSE;
12275  if( !SCIPisIntegral(scip, vals[v]) )
12276  allcoefintegral = FALSE;
12277  }
12278 
12279  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12280  * hand side or bigger than the left hand side respectively, so we can make all of them integral
12281  *
12282  * @todo there are some steps missing ....
12283  */
12284  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12285  {
12286  SCIP_Real val;
12287  SCIP_Real newval;
12288  SCIP_Real frac = 0.0;
12289  SCIP_Bool found = FALSE;
12290 
12291  if( hasrhs )
12292  {
12293  if( allcoefintegral )
12294  {
12295  /* replace old with new right hand side */
12296  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12297  ++(*nchgsides);
12298  }
12299  else
12300  {
12301  siderest = rhs - SCIPfloor(scip, rhs);
12302 
12303  /* try to round down all non-integral coefficients */
12304  for( v = nvars - 1; v >= 0; --v )
12305  {
12306  val = vals[v];
12307 
12308  /* add up all possible fractional parts */
12309  if( !SCIPisIntegral(scip, val) )
12310  {
12311  lb = SCIPvarGetLbGlobal(vars[v]);
12312  ub = SCIPvarGetUbGlobal(vars[v]);
12313 
12314  /* at least one bound need to be at zero */
12315  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12316  return SCIP_OKAY;
12317 
12318  /* swap bounds for 'standard' form */
12319  if( !SCIPisFeasZero(scip, lb) )
12320  {
12321  ub = lb;
12322  val *= -1;
12323  }
12324 
12325  found = TRUE;
12326 
12327  frac += (val - SCIPfloor(scip, val)) * ub;
12328 
12329  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12330  *
12331  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12332  * x3, x4 set to 1 would be infeasible but feasible after flooring
12333  */
12334  if( SCIPisGT(scip, frac, siderest) )
12335  return SCIP_OKAY;
12336  }
12337  }
12338  assert(v == -1);
12339 
12340  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12341 
12342  /* round rhs and coefficients to integral values */
12343  if( found )
12344  {
12345  for( v = nvars - 1; v >= 0; --v )
12346  {
12347  val = vals[v];
12348 
12349  /* add the whole fractional part */
12350  if( !SCIPisIntegral(scip, val) )
12351  {
12352  lb = SCIPvarGetLbGlobal(vars[v]);
12353 
12354  if( SCIPisFeasZero(scip, lb) )
12355  newval = SCIPfloor(scip, val);
12356  else
12357  newval = SCIPceil(scip, val);
12358 
12359  if( SCIPisZero(scip, newval) )
12360  {
12361  /* delete old redundant coefficient */
12362  SCIP_CALL( delCoefPos(scip, cons, v) );
12363  ++(*nchgcoefs);
12364  }
12365  else
12366  {
12367  /* replace old with new coefficient */
12368  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12369  ++(*nchgcoefs);
12370  }
12371  }
12372  }
12373  }
12374 
12375  /* replace old with new right hand side */
12376  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12377  ++(*nchgsides);
12378  }
12379  }
12380  else
12381  {
12382  if( allcoefintegral )
12383  {
12384  /* replace old with new left hand side */
12385  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12386  ++(*nchgsides);
12387  }
12388  else
12389  {
12390  /* cannot floor left hand side to zero */
12391  if( SCIPisLT(scip, lhs, 1.0) )
12392  return SCIP_OKAY;
12393 
12394  siderest = lhs - SCIPfloor(scip, lhs);
12395 
12396  /* try to round down all non-integral coefficients */
12397  for( v = nvars - 1; v >= 0; --v )
12398  {
12399  val = vals[v];
12400 
12401  /* add up all possible fractional parts */
12402  if( !SCIPisIntegral(scip, val) )
12403  {
12404  lb = SCIPvarGetLbGlobal(vars[v]);
12405  ub = SCIPvarGetUbGlobal(vars[v]);
12406 
12407  /* at least one bound need to be at zero */
12408  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12409  return SCIP_OKAY;
12410 
12411  /* swap bounds for 'standard' form */
12412  if( !SCIPisFeasZero(scip, lb) )
12413  {
12414  ub = lb;
12415  val *= -1;
12416  }
12417 
12418  /* cannot floor to zero */
12419  if( SCIPisLT(scip, val, 1.0) )
12420  return SCIP_OKAY;
12421 
12422  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12423  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12424  return SCIP_OKAY;
12425 
12426  found = TRUE;
12427 
12428  frac += (val - SCIPfloor(scip, val)) * ub;
12429 
12430  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12431  * fractional parts of the variables, we cannot tighten the coefficients
12432  *
12433  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12434  * x2-x4 set to 1 would be feasible but not after flooring
12435  */
12436  if( SCIPisGE(scip, frac, 1 + siderest) )
12437  return SCIP_OKAY;
12438  }
12439  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12440  else
12441  return SCIP_OKAY;
12442  }
12443  assert(v == -1);
12444 
12445  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12446 
12447  /* round lhs and coefficients to integral values */
12448  if( found )
12449  {
12450  for( v = nvars - 1; v >= 0; --v )
12451  {
12452  val = vals[v];
12453 
12454  /* add the whole fractional part */
12455  if( !SCIPisIntegral(scip, val) )
12456  {
12457  lb = SCIPvarGetLbGlobal(vars[v]);
12458 
12459  if( SCIPisFeasZero(scip, lb) )
12460  newval = SCIPfloor(scip, val);
12461  else
12462  newval = SCIPceil(scip, val);
12463 
12464  if( SCIPisZero(scip, newval) )
12465  {
12466  /* delete old redundant coefficient */
12467  SCIP_CALL( delCoefPos(scip, cons, v) );
12468  ++(*nchgcoefs);
12469  }
12470  else
12471  {
12472  /* replace old with new coefficient */
12473  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12474  ++(*nchgcoefs);
12475  }
12476  }
12477  }
12478  }
12479 
12480  /* replace old with new left hand side */
12481  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12482  ++(*nchgsides);
12483  }
12484  }
12485 
12486  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12487  assert(vars == consdata->vars);
12488  assert(vals == consdata->vals);
12489 
12490  if( *infeasible )
12491  return SCIP_OKAY;
12492 
12493  rhs = consdata->rhs;
12494  lhs = consdata->lhs;
12495 
12496  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12497  assert(!haslhs || !SCIPisNegative(scip, lhs));
12498 
12499  SCIPdebugPrintCons(scip, cons, NULL);
12500 
12501  nvars = consdata->nvars;
12502  if( nvars < 2 )
12503  return SCIP_OKAY;
12504 
12505  allcoefintegral = TRUE;
12506 #ifndef NDEBUG
12507  /* debug check if all coefficients are really integral */
12508  for( v = nvars - 1; v >= 0; --v )
12509  assert(SCIPisIntegral(scip, vals[v]));
12510 #endif
12511  }
12512 
12513  /* @todo following can also work on non integral coefficients, need more investigation */
12514  /* only check constraints with integral coefficients on all integral variables */
12515  if( !allcoefintegral )
12516  return SCIP_OKAY;
12517 
12518  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12519  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12520  return SCIP_OKAY;
12521 
12522  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12523  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12524  return SCIP_OKAY;
12525 
12526  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12527  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12528  return SCIP_OKAY;
12529 
12530  assert(nvars >= 2);
12531 
12532  /* start gcd procedure for all variables */
12533  do
12534  {
12535  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12536  SCIPdebug( oldnchgsides = *nchgsides; )
12537 
12538  /* stop if we have two coeffcients which are one in absolute value */
12539  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12540  return SCIP_OKAY;
12541 
12542  gcd = -1;
12543 
12544  /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12545  * because coefficients of non-binary variables might have changed to zero */
12546  if( !onlybin )
12547  {
12548  foundbin = -1;
12549  onlybin = TRUE;
12550 
12551  for( v = nvars - 1; v >= 0; --v )
12552  {
12553  assert(!SCIPisZero(scip, vals[v]));
12554  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12555 
12556  if( SCIPvarIsBinary(vars[v]) )
12557  {
12558  if( foundbin == -1 )
12559  foundbin = v;
12560  continue;
12561  }
12562  else
12563  onlybin = FALSE;
12564 
12565  absval = REALABS(vals[v]);
12566  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12567  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12568  */
12569  assert(SCIPisFeasIntegral(scip, absval));
12570 
12571  if( gcd == -1 )
12572  {
12573  gcd = (SCIP_Longint)(absval + feastol);
12574  assert(gcd >= 1);
12575  }
12576  else
12577  {
12578  /* calculate greatest common divisor for all general variables */
12579  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12580  }
12581  if( gcd == 1 )
12582  break;
12583  }
12584  }
12585  else
12586  foundbin = nvars - 1;
12587 
12588  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12589  if( gcd == 1 || foundbin == -1)
12590  return SCIP_OKAY;
12591 
12592  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12593 
12594  candpos = -1;
12595  candpos2 = -1;
12596 
12597  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12598  * change the coefficient
12599  */
12600  for( v = foundbin; v >= 0; --v )
12601  {
12602  if( onlybin || SCIPvarIsBinary(vars[v]) )
12603  {
12604  absval = REALABS(vals[v]);
12605  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12606  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12607  */
12608  assert(SCIPisFeasIntegral(scip, absval));
12609 
12610  oldgcd = gcd;
12611 
12612  if( gcd == -1 )
12613  {
12614  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12615  assert(gcd >= 1);
12616  }
12617  else
12618  {
12619  /* calculate greatest common divisor for all general and binary variables */
12620  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12621  }
12622 
12623  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12624  * can terminate
12625  */
12626  if( gcd == 1 )
12627  {
12628  /* found candidate */
12629  if( candpos == -1 )
12630  {
12631  gcd = oldgcd;
12632  candpos = v;
12633 
12634  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12635  * the coefficient change
12636  */
12637  if( onlybin && v == foundbin - 1 )
12638  candpos2 = foundbin;
12639  }
12640  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12641  else
12642  {
12643  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12644  {
12645  assert(candpos2 == nvars - 1);
12646 
12647  /* take new candidates */
12648  candpos = candpos2;
12649 
12650  /* recalculate gcd from scratch */
12651  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12652  assert(gcd >= 1);
12653 
12654  /* calculate greatest common divisor for all general and binary variables */
12655  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12656  if( gcd == 1 )
12657  return SCIP_OKAY;
12658  }
12659  else
12660  /* cannot determine a possible coefficient for reduction */
12661  return SCIP_OKAY;
12662  }
12663  }
12664  }
12665  }
12666  assert(gcd >= 2);
12667 
12668  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12669  * further
12670  */
12671  assert(candpos >= 0 && candpos < nvars);
12672 
12673  /* all variables and all coefficients are integral, so the side should be too */
12674  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12675 
12676  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12677  * @see normalizeCons()
12678  */
12679  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12680  assert(!haslhs || !SCIPisNegative(scip, lhs));
12681 
12682  /* determine the remainder of the side and the gcd */
12683  if( hasrhs )
12684  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12685  else
12686  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12687  assert(rest >= 0);
12688  assert(rest < gcd);
12689 
12690  /* determine the remainder of the coefficient candidate and the gcd */
12691  if( vals[candpos] < 0 )
12692  {
12693  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12694  assert(restcoef <= -1);
12695  restcoef += gcd;
12696  }
12697  else
12698  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12699  assert(restcoef >= 1);
12700  assert(restcoef < gcd);
12701 
12702  if( hasrhs )
12703  {
12704  if( rest > 0 )
12705  {
12706  /* replace old with new right hand side */
12707  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12708  ++(*nchgsides);
12709  }
12710 
12711  /* calculate new coefficient */
12712  if( restcoef > rest )
12713  newcoef = vals[candpos] - restcoef + gcd;
12714  else
12715  newcoef = vals[candpos] - restcoef;
12716  }
12717  else
12718  {
12719  if( rest > 0 )
12720  {
12721  /* replace old with new left hand side */
12722  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12723  ++(*nchgsides);
12724  }
12725 
12726  /* calculate new coefficient */
12727  if( rest == 0 || restcoef < rest )
12728  newcoef = vals[candpos] - restcoef;
12729  else
12730  newcoef = vals[candpos] - restcoef + gcd;
12731  }
12732  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12733 
12734  SCIPdebugMsg(scip, "gcd = %" SCIP_LONGINT_FORMAT ", rest = %" SCIP_LONGINT_FORMAT ", restcoef = %" SCIP_LONGINT_FORMAT "; changing coef of variable <%s> to %g and %s by %" SCIP_LONGINT_FORMAT "\n", gcd, rest, restcoef, SCIPvarGetName(vars[candpos]), newcoef, hasrhs ? "reduced rhs" : "increased lhs", hasrhs ? rest : (rest > 0 ? gcd - rest : 0));
12735 
12736  if( SCIPisZero(scip, newcoef) )
12737  {
12738  /* delete redundant coefficient */
12739  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12740  }
12741  else
12742  {
12743  /* replace old with new coefficient */
12744  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12745  }
12746  ++(*nchgcoefs);
12747 
12748  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12749  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12750  assert(vars == consdata->vars);
12751  assert(vals == consdata->vals);
12752 
12753  if( *infeasible )
12754  return SCIP_OKAY;
12755 
12756  SCIPdebugPrintCons(scip, cons, NULL);
12757 
12758  rhs = consdata->rhs;
12759  lhs = consdata->lhs;
12760  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12761  assert(!haslhs || !SCIPisNegative(scip, lhs));
12762 
12763  nvars = consdata->nvars;
12764 
12765  SCIPdebugMsg(scip, "we did %d coefficient changes and %d side changes on constraint %s when applying one round of the gcd algorithm\n", *nchgcoefs - oldnchgcoefs, *nchgsides - oldnchgsides, SCIPconsGetName(cons));
12766  }
12767  while( nvars >= 2 );
12768 
12769  return SCIP_OKAY;
12770 }
12771 
12772 
12773 /** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12774  * cons0 := a * cons0 + b * cons1,
12775  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12776  * for numerical stability, we will only accept integral a and b;
12777  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12778  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12779  */
12780 static
12782  SCIP* scip, /**< SCIP data structure */
12783  SCIP_CONS* cons0, /**< (in)equality to modify */
12784  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12785  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12786  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12787  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12788  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12789  int nvarscommon, /**< number of variables, that appear in both constraints */
12790  int commonidxweight, /**< variable weight sum of common variables */
12791  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12792  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12793  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12794  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12795  SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12796  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12797  )
12798 {
12799  SCIP_CONSDATA* consdata0;
12800  SCIP_CONSDATA* consdata1;
12801  SCIP_Real a;
12802  SCIP_Real b;
12803  SCIP_Real aggrcoef;
12804  SCIP_Real scalarsum;
12805  SCIP_Real bestscalarsum;
12806  SCIP_Bool betterscalarsum;
12807  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12808  int varweight;
12809  int nvars;
12810  int bestvarweight;
12811  int bestnvars;
12812  int bestv;
12813  int v;
12814  int i;
12815 
12816  assert(scip != NULL);
12817  assert(cons0 != NULL);
12818  assert(cons1 != NULL);
12819  assert(commonidx0 != NULL);
12820  assert(commonidx1 != NULL);
12821  assert(diffidx0minus1 != NULL);
12822  assert(diffidx1minus0 != NULL);
12823  assert(nvarscommon >= 1);
12824  assert(commonidxweight >= nvarscommon);
12825  assert(nchgcoefs != NULL);
12826  assert(aggregated != NULL);
12827 
12828  assert(SCIPconsIsActive(cons0));
12829  assert(SCIPconsIsActive(cons1));
12830 
12831  *infeasible = FALSE;
12832 
12833  SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12834 
12835  /* cons0 is an (in)equality */
12836  consdata0 = SCIPconsGetData(cons0);
12837  assert(consdata0 != NULL);
12838  assert(consdata0->nvars >= 1);
12839  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12840  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12841 
12842  /* cons1 is an equality */
12843  consdata1 = SCIPconsGetData(cons1);
12844  assert(consdata1 != NULL);
12845  assert(consdata1->nvars >= 1);
12846  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12847  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12848 
12849  *aggregated = FALSE;
12850 
12851  /* search for the best common variable such that
12852  * val1[var] * consdata0 - val0[var] * consdata1
12853  * has least weighted number of variables
12854  */
12855  bestvarweight = commonidxweight + diffidx0minus1weight;
12856  bestnvars = consdata0->nvars;
12857  bestv = -1;
12858  bestscalarsum = 0.0;
12859  commonvarlindependent = TRUE;
12860  for( v = 0; v < nvarscommon; ++v )
12861  {
12862  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12863  a = consdata1->vals[commonidx1[v]];
12864  b = -consdata0->vals[commonidx0[v]];
12865 
12866  /* only try aggregation, if coefficients are integral (numerical stability) */
12867  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12868  {
12869  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12870  varweight = diffidx0minus1weight + diffidx1minus0weight;
12871  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12872  scalarsum = REALABS(a) + REALABS(b);
12873  betterscalarsum = (scalarsum < bestscalarsum);
12874  for( i = 0; i < nvarscommon
12875  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12876  {
12877  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12878  if( !SCIPisZero(scip, aggrcoef) )
12879  {
12880  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12881  nvars++;
12882  }
12883  }
12884  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12885  {
12886  bestv = v;
12887  bestvarweight = varweight;
12888  bestnvars = nvars;
12889  bestscalarsum = scalarsum;
12890  }
12891  }
12892 
12893  /* update commonvarlindependent flag, if still TRUE:
12894  * v's common coefficient in cons1 / v's common coefficient in cons0 should be constant, i.e., equal 0's common coefficient in cons1 / 0's common coefficient in cons0
12895  */
12896  if( commonvarlindependent && v > 0 )
12897  commonvarlindependent = SCIPisEQ(scip,
12898  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12899  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12900  }
12901 
12902  /* if better aggregation was found, create new constraint and delete old one */
12903  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12904  {
12905  SCIP_CONS* newcons;
12906  SCIP_CONSDATA* newconsdata;
12907  SCIP_VAR** newvars;
12908  SCIP_Real* newvals;
12909  SCIP_Real newlhs;
12910  SCIP_Real newrhs;
12911  int newnvars;
12912 
12913  if( bestv != -1 )
12914  {
12915  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12916  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12917  {
12918  a = consdata1->vals[commonidx1[bestv]];
12919  b = -consdata0->vals[commonidx0[bestv]];
12920  }
12921  else
12922  {
12923  a = -consdata1->vals[commonidx1[bestv]];
12924  b = consdata0->vals[commonidx0[bestv]];
12925  }
12926  assert(SCIPisIntegral(scip, a));
12927  assert(SCIPisPositive(scip, a));
12928  assert(SCIPisIntegral(scip, b));
12929  assert(!SCIPisZero(scip, b));
12930  }
12931  else
12932  {
12933  assert(commonvarlindependent);
12934  if( consdata1->vals[commonidx1[0]] > 0.0 )
12935  {
12936  a = consdata1->vals[commonidx1[0]];
12937  b = -consdata0->vals[commonidx0[0]];
12938  }
12939  else
12940  {
12941  a = -consdata1->vals[commonidx1[0]];
12942  b = consdata0->vals[commonidx0[0]];
12943  }
12944  assert(SCIPisPositive(scip, a));
12945  assert(!SCIPisZero(scip, b));
12946 
12947  /* if a/b is integral, then we can easily choose integer multipliers */
12948  if( SCIPisIntegral(scip, a/b) )
12949  {
12950  if( a/b > 0 )
12951  {
12952  a /= b;
12953  b = 1.0;
12954  }
12955  else
12956  {
12957  a /= -b;
12958  b = -1.0;
12959  }
12960  }
12961 
12962  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12963  SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12964  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12965  }
12966 
12967  SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12968  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12969  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12970  SCIPdebugPrintCons(scip, cons0, NULL);
12971  SCIPdebugPrintCons(scip, cons1, NULL);
12972 
12973  /* get temporary memory for creating the new linear constraint */
12974  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12975  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12976 
12977  /* calculate the common coefficients, if we have not recognized linear dependency */
12978  newnvars = 0;
12979  if( !commonvarlindependent )
12980  {
12981  for( i = 0; i < nvarscommon; ++i )
12982  {
12983  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12984  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12985 
12986  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12987  if( !SCIPisZero(scip, aggrcoef) )
12988  {
12989  assert(newnvars < bestnvars);
12990  newvars[newnvars] = consdata0->vars[commonidx0[i]];
12991  newvals[newnvars] = aggrcoef;
12992  newnvars++;
12993  }
12994  }
12995  }
12996  else
12997  {
12998  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12999 #ifndef NDEBUG
13000  for( i = 0; i < nvarscommon; ++i )
13001  {
13002  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
13003  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
13004 
13005  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
13006  assert(SCIPisZero(scip, aggrcoef));
13007  }
13008 #endif
13009  }
13010 
13011  /* calculate the coefficients appearing in cons0 but not in cons1 */
13012  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
13013  {
13014  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
13015 
13016  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
13017  assert(!SCIPisZero(scip, aggrcoef));
13018  assert(newnvars < bestnvars);
13019  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
13020  newvals[newnvars] = aggrcoef;
13021  newnvars++;
13022  }
13023 
13024  /* calculate the coefficients appearing in cons1 but not in cons0 */
13025  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
13026  {
13027  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
13028 
13029  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
13030  assert(!SCIPisZero(scip, aggrcoef));
13031  assert(newnvars < bestnvars);
13032  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
13033  newvals[newnvars] = aggrcoef;
13034  newnvars++;
13035  }
13036  assert(newnvars == bestnvars);
13037 
13038  /* calculate the new left and right hand side of the (in)equality */
13039  assert(!SCIPisInfinity(scip, -consdata1->lhs));
13040  assert(!SCIPisInfinity(scip, consdata1->rhs));
13041  if( SCIPisInfinity(scip, -consdata0->lhs) )
13042  newlhs = -SCIPinfinity(scip);
13043  else
13044  newlhs = a * consdata0->lhs + b * consdata1->lhs;
13045  if( SCIPisInfinity(scip, consdata0->rhs) )
13046  newrhs = SCIPinfinity(scip);
13047  else
13048  newrhs = a * consdata0->rhs + b * consdata1->rhs;
13049 
13050  /* create the new linear constraint */
13051  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
13053  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
13054  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
13056 
13057  newconsdata = SCIPconsGetData(newcons);
13058  assert(newconsdata != NULL);
13059 
13060  /* copy the upgraded flag from the old cons0 to the new constraint */
13061  newconsdata->upgraded = consdata0->upgraded;
13062 
13063  SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
13064 
13065  if( *infeasible )
13066  goto TERMINATE;
13067 
13068  /* check, if we really want to use the new constraint instead of the old one:
13069  * use the new one, if the maximum norm doesn't grow too much
13070  */
13071  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
13072  {
13073  SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
13074  SCIPdebugPrintCons(scip, newcons, NULL);
13075 
13076  /* update the statistics: we changed all coefficients */
13077  if( !consdata0->upgraded )
13078  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
13079  *aggregated = TRUE;
13080 
13081  /* delete the old constraint, and add the new linear constraint to the problem */
13082  SCIP_CALL( SCIPdelCons(scip, cons0) );
13083  SCIP_CALL( SCIPaddCons(scip, newcons) );
13084  }
13085 
13086  TERMINATE:
13087  /* release the new constraint */
13088  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
13089 
13090  /* free temporary memory */
13091  SCIPfreeBufferArray(scip, &newvals);
13092  SCIPfreeBufferArray(scip, &newvars);
13093  }
13094 
13095  return SCIP_OKAY;
13096 }
13097 
13098 /** gets the key of the given element */
13099 static
13100 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
13101 { /*lint --e{715}*/
13102  /* the key is the element itself */
13103  return elem;
13104 }
13105 
13106 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13107  * coefficients are either equal or negated
13108  */
13109 static
13110 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
13111 {
13112  SCIP* scip;
13113  SCIP_CONSDATA* consdata1;
13114  SCIP_CONSDATA* consdata2;
13115  SCIP_Real cons1scale;
13116  SCIP_Real cons2scale;
13117  int i;
13118 
13119  assert(key1 != NULL);
13120  assert(key2 != NULL);
13121  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13122  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13123  assert(consdata1->indexsorted);
13124  assert(consdata2->indexsorted);
13125 
13126  scip = (SCIP*)userptr;
13127  assert(scip != NULL);
13128 
13129  /* if it is the same constraint we dont need to check anything */
13130  if( key1 == key2 )
13131  return TRUE;
13132 
13133  /* checks trivial case */
13134  if( consdata1->nvars != consdata2->nvars )
13135  return FALSE;
13136 
13137  /* tests if variables are equal */
13138  for( i = 0; i < consdata1->nvars; ++i )
13139  {
13140  if( consdata1->vars[i] != consdata2->vars[i] )
13141  {
13142  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13143  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13144  return FALSE;
13145  }
13146  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13147  }
13148 
13149  /* compute scale before comparing coefficients of constraints */
13150  cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
13151  cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
13152 
13153  /* tests if coefficients are equal with the computed scale */
13154  for( i = 0; i < consdata1->nvars; ++i )
13155  {
13156  SCIP_Real val1;
13157  SCIP_Real val2;
13158 
13159  val1 = consdata1->vals[i] * cons1scale;
13160  val2 = consdata2->vals[i] * cons2scale;
13161 
13162  if( !SCIPisEQ(scip, val1, val2) )
13163  return FALSE;
13164  }
13165 
13166  return TRUE;
13167 }
13168 
13169 /** returns the hash value of the key */
13170 static
13171 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13172 {
13173  SCIP_CONSDATA* consdata;
13174  int minidx;
13175  int mididx;
13176  int maxidx;
13177  SCIP_Real scale;
13178 #ifndef NDEBUG
13179  SCIP* scip;
13180 
13181  scip = (SCIP*)userptr;
13182  assert(scip != NULL);
13183 #endif
13184 
13185  assert(key != NULL);
13186  consdata = SCIPconsGetData((SCIP_CONS*)key);
13187  assert(consdata != NULL);
13188  assert(consdata->nvars > 0);
13189 
13190  assert(consdata->indexsorted);
13191 
13192  minidx = SCIPvarGetIndex(consdata->vars[0]);
13193  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13194  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13195  scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
13196 
13197  /* using only the variable indices as hash, since the values are compared by epsilon */
13198  return SCIPhashSeven(consdata->nvars, minidx, SCIPrealHashCode(consdata->vals[0] * scale),
13199  mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale),
13200  maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale));
13201 }
13202 
13203 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13204  * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13205  */
13206 static
13207 unsigned int getParallelConsKey(
13208  SCIP_CONS* cons /**< linear constraint */
13209  )
13210 {
13211  SCIP_CONSDATA* consdata;
13212 
13213  assert(cons != NULL);
13214 
13215  consdata = SCIPconsGetData(cons);
13216  assert(consdata != NULL);
13217 
13218  return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13219 }
13220 
13221 /** updates the hashtable such that out of all constraints in the hashtable that are detected
13222  * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13223  * and all others are removed from the hashtable and stored in the given array
13224  */
13225 static
13227  SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13228  SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13229  * upon return will contain the constraint that should be kept */
13230  SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13231  * these constraints where removed from the hashtable */
13232  int* nparallelconss /**< pointer to return number of parallel constraints */
13233  )
13234 {
13235  SCIP_CONS* parallelcons;
13236  unsigned int querykey;
13237 
13238  *nparallelconss = 0;
13239  querykey = getParallelConsKey(*querycons);
13240 
13241  while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13242  {
13243  unsigned int conskey = getParallelConsKey(parallelcons);
13244 
13245  if( conskey < querykey )
13246  {
13247  parallelconss[(*nparallelconss)++] = *querycons;
13248  *querycons = parallelcons;
13249  querykey = conskey;
13250  }
13251  else
13252  {
13253  parallelconss[(*nparallelconss)++] = parallelcons;
13254  }
13255 
13256  /* if the constraint that just came out of the hash table is the one that is kept,
13257  * we do not need to look into the hashtable again, since the invariant is that
13258  * in the hashtable only pair-wise non-parallel constraints are contained.
13259  * For the original querycons, however, multiple constraints that compare equal (=parallel)
13260  * could be contained due to non-transitivity of the equality comparison.
13261  * Also we can return immediately, since parallelcons is already contained in the
13262  * hashtable and we do not need to remove and reinsert it.
13263  */
13264  if( *querycons == parallelcons )
13265  return SCIP_OKAY;
13266 
13267  /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13268  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13269  }
13270 
13271  /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13272  * comnpares equal to querycons at this point
13273  */
13274 #ifndef NDEBUG
13275  SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13276 #else
13277  SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13278 #endif
13279 
13280  return SCIP_OKAY;
13281 }
13282 
13283 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13284  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13285  */
13286 static
13288  SCIP* scip, /**< SCIP data structure */
13289  BMS_BLKMEM* blkmem, /**< block memory */
13290  SCIP_CONS** conss, /**< constraint set */
13291  int nconss, /**< number of constraints in constraint set */
13292  int* firstchange, /**< pointer to store first changed constraint */
13293  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13294  int* ndelconss, /**< pointer to count number of deleted constraints */
13295  int* nchgsides /**< pointer to count number of changed left/right hand sides */
13296  )
13297 {
13298  SCIP_HASHTABLE* hashtable;
13299  SCIP_CONS** parallelconss;
13300  int nparallelconss;
13301  int hashtablesize;
13302  int c;
13303 
13304  assert(scip != NULL);
13305  assert(blkmem != NULL);
13306  assert(conss != NULL);
13307  assert(firstchange != NULL);
13308  assert(cutoff != NULL);
13309  assert(ndelconss != NULL);
13310  assert(nchgsides != NULL);
13311 
13312  /* create a hash table for the constraint set */
13313  hashtablesize = nconss;
13314  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13315  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13316 
13317  SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13318 
13319  /* check all constraints in the given set for redundancy */
13320  for( c = 0; c < nconss; ++c )
13321  {
13322  SCIP_CONS* cons0;
13323  SCIP_CONSDATA* consdata0;
13324 
13325  cons0 = conss[c];
13326 
13327  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13328  continue;
13329 
13330  /* do not check for parallel constraints if they should not be upgraded */
13331  if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13332  continue;
13333 
13334  /* check for interuption */
13335  if( c % 1000 == 0 && SCIPisStopped(scip) )
13336  break;
13337 
13338  /* sorts the constraint */
13339  consdata0 = SCIPconsGetData(cons0);
13340  assert(consdata0 != NULL);
13341  SCIP_CALL( consdataSort(scip, consdata0) );
13342  assert(consdata0->indexsorted);
13343 
13344  /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13345  * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13346  * first variable is positive
13347  * Also inserts cons0 into the hashtable.
13348  */
13349  SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13350 
13351  if( nparallelconss != 0 )
13352  {
13353  SCIP_Real lhs;
13354  SCIP_Real rhs;
13355 
13356  int i;
13357 
13358  /* cons0 may have been changed in retrieveParallelConstraints() */
13359  consdata0 = SCIPconsGetData(cons0);
13360 
13361  lhs = consdata0->lhs;
13362  rhs = consdata0->rhs;
13363 
13364  for( i = 0; i < nparallelconss; ++i )
13365  {
13366  SCIP_CONS* consdel;
13367  SCIP_CONSDATA* consdatadel;
13368  SCIP_Real scale;
13369 
13370  consdel = parallelconss[i];
13371  consdatadel = SCIPconsGetData(consdel);
13372 
13373  /* do not delete constraint if it should not be upgraded */
13374  if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13375  continue;
13376 
13377  assert(SCIPconsIsActive(consdel));
13378  assert(!SCIPconsIsModifiable(consdel));
13379 
13380  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13381  * delete old constraints afterwards
13382  */
13383  assert(consdatadel != NULL);
13384  assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13385 
13386  assert(consdatadel->indexsorted);
13387  assert(consdata0->vars[0] == consdatadel->vars[0]);
13388 
13389  scale = consdata0->vals[0] / consdatadel->vals[0];
13390  assert(scale != 0.0);
13391 
13392  /* in debug mode, check that all coefficients are equal with respect to epsilon
13393  * if the constraints are in equilibrium scale
13394  */
13395 #ifndef NDEBUG
13396  {
13397  int k;
13398  SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13399  SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13400 
13401  for( k = 0; k < consdata0->nvars; ++k )
13402  {
13403  assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13404  }
13405  }
13406 #endif
13407 
13408  if( scale > 0.0 )
13409  {
13410  /* the coefficients of both constraints are parallel with a positive scale */
13411  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal 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->lhs) )
13417  lhs = MAX(scale * consdatadel->lhs, lhs);
13418 
13419  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13420  rhs = MIN(scale * consdatadel->rhs, rhs);
13421  }
13422  else
13423  {
13424  /* the coefficients of both rows are negations */
13425  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13426  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13427  SCIPdebugPrintCons(scip, cons0, NULL);
13428  SCIPdebugPrintCons(scip, consdel, NULL);
13429 
13430  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13431  lhs = MAX(scale * consdatadel->rhs, lhs);
13432 
13433  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13434  rhs = MIN(scale * consdatadel->lhs, rhs);
13435  }
13436 
13437  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13438  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13439 
13440  /* delete consdel */
13441  assert( ! consdata0->upgraded || consdatadel->upgraded );
13442  SCIP_CALL( SCIPdelCons(scip, consdel) );
13443  if( !consdatadel->upgraded )
13444  (*ndelconss)++;
13445  }
13446 
13447  if( SCIPisFeasLT(scip, rhs, lhs) )
13448  {
13449  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13450  *cutoff = TRUE;
13451  break;
13452  }
13453 
13454  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13455  if( lhs > rhs )
13456  {
13457  rhs = (lhs + rhs)/2;
13458  lhs = rhs;
13459  }
13460 
13461  /* update lhs and rhs of cons0 */
13462  SCIP_CALL( chgLhs(scip, cons0, lhs) );
13463  SCIP_CALL( chgRhs(scip, cons0, rhs) );
13464 
13465  /* update the first changed constraint to begin the next aggregation round with */
13466  if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13467  *firstchange = SCIPconsGetPos(cons0);
13468 
13469  assert(SCIPconsIsActive(cons0));
13470  }
13471  }
13472 #ifdef SCIP_MORE_DEBUG
13473  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13475 #endif
13476 
13477  SCIPfreeBufferArray(scip, &parallelconss);
13478 
13479  /* free hash table */
13480  SCIPhashtableFree(&hashtable);
13481 
13482  return SCIP_OKAY;
13483 }
13484 
13485 /** compares constraint with all prior constraints for possible redundancy or aggregation,
13486  * and removes or changes constraint accordingly
13487  */
13488 static
13490  SCIP* scip, /**< SCIP data structure */
13491  SCIP_CONS** conss, /**< constraint set */
13492  int firstchange, /**< first constraint that changed since last pair preprocessing round */
13493  int chkind, /**< index of constraint to check against all prior indices upto startind */
13494  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13495  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13496  int* ndelconss, /**< pointer to count number of deleted constraints */
13497  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13498  int* nchgcoefs /**< pointer to count number of changed coefficients */
13499  )
13500 {
13501  SCIP_CONS* cons0;
13502  SCIP_CONSDATA* consdata0;
13503  int* commonidx0;
13504  int* commonidx1;
13505  int* diffidx0minus1;
13506  int* diffidx1minus0;
13507  uint64_t possignature0;
13508  uint64_t negsignature0;
13509  SCIP_Bool cons0changed;
13510  SCIP_Bool cons0isequality;
13511  int diffidx1minus0size;
13512  int c;
13513  SCIP_Real cons0lhs;
13514  SCIP_Real cons0rhs;
13515  SCIP_Bool cons0upgraded;
13516 
13517  assert(scip != NULL);
13518  assert(conss != NULL);
13519  assert(firstchange <= chkind);
13520  assert(cutoff != NULL);
13521  assert(ndelconss != NULL);
13522  assert(nchgsides != NULL);
13523  assert(nchgcoefs != NULL);
13524 
13525  /* get the constraint to be checked against all prior constraints */
13526  cons0 = conss[chkind];
13527  assert(cons0 != NULL);
13528  assert(SCIPconsIsActive(cons0));
13529  assert(!SCIPconsIsModifiable(cons0));
13530 
13531  consdata0 = SCIPconsGetData(cons0);
13532  assert(consdata0 != NULL);
13533  assert(consdata0->nvars >= 1);
13534  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13535 
13536  /* sort the constraint */
13537  SCIP_CALL( consdataSort(scip, consdata0) );
13538 
13539  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13540  consdataCalcSignatures(consdata0);
13541  possignature0 = consdata0->possignature;
13542  negsignature0 = consdata0->negsignature;
13543 
13544  /* get temporary memory for indices of common variables */
13545  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13546  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13547  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13548  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13549  diffidx1minus0size = consdata0->nvars;
13550 
13551  cons0lhs = consdata0->lhs;
13552  cons0rhs = consdata0->rhs;
13553  cons0upgraded = consdata0->upgraded;
13554 
13555  /* check constraint against all prior constraints */
13556  cons0changed = consdata0->changed;
13557  consdata0->changed = FALSE;
13558  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13559  {
13560  SCIP_CONS* cons1;
13561  SCIP_CONSDATA* consdata1;
13562  uint64_t possignature1;
13563  uint64_t negsignature1;
13564  SCIP_Bool cons0dominateslhs;
13565  SCIP_Bool cons1dominateslhs;
13566  SCIP_Bool cons0dominatesrhs;
13567  SCIP_Bool cons1dominatesrhs;
13568  SCIP_Bool cons1isequality;
13569  SCIP_Bool coefsequal;
13570  SCIP_Bool coefsnegated;
13571  SCIP_Bool tryaggregation;
13572  int nvarscommon;
13573  int nvars0minus1;
13574  int nvars1minus0;
13575  int commonidxweight;
13576  int diffidx0minus1weight;
13577  int diffidx1minus0weight;
13578  int v0;
13579  int v1;
13580 
13581  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13582  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13583  assert(cons0upgraded == consdata0->upgraded);
13584 
13585  cons1 = conss[c];
13586 
13587  /* cons1 has become inactive during presolving of constraint pairs */
13588  if( cons1 == NULL )
13589  continue;
13590 
13591  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13592  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13593 
13594  consdata1 = SCIPconsGetData(cons1);
13595  assert(consdata1 != NULL);
13596 
13597  /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13598  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13599  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13600 
13601  /* if both constraints didn't change since last pair processing, we can ignore the pair */
13602  if( !cons0changed && !consdata1->changed )
13603  continue;
13604 
13605  /* if both constraints are already upgraded, skip the pair;
13606  * because changes on these constraints cannot be applied to the instance anymore */
13607  if( cons0upgraded && consdata1->upgraded )
13608  continue;
13609 
13610  assert(consdata1->nvars >= 1);
13611 
13612  /* sort the constraint */
13613  SCIP_CALL( consdataSort(scip, consdata1) );
13614 
13615  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13616  consdataCalcSignatures(consdata1);
13617  possignature1 = consdata1->possignature;
13618  negsignature1 = consdata1->negsignature;
13619 
13620  /* the signatures give a quick test to check for domination and equality of coefficients */
13621  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13622  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13623  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13624  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13625  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13626  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13627  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13628  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13629  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13630  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13631  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13632  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13633  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13634  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13635  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13636  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13637  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13638  && !coefsequal && !coefsnegated && !tryaggregation )
13639  continue;
13640 
13641  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13642  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13643  {
13644  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13645  diffidx1minus0size = consdata1->nvars;
13646  }
13647 
13648  /* check consdata0 against consdata1:
13649  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13650  * consdata0 dominates consdata1 w.r.t. left hand side
13651  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13652  * consdata0 dominates consdata1 w.r.t. right hand side
13653  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13654  * ranged row (or equality)
13655  * - if at least one constraint is an equality, count the weighted number of common variables W_c
13656  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13657  * where the weight of each variable depends on its type, such that aggregations in order to remove the
13658  * number of continuous and integer variables are preferred:
13659  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13660  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13661  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13662  * to be positive to not switch the sense of the (in)equality cons0
13663  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13664  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13665  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13666  * to be positive to not switch the sense of the (in)equality cons1
13667  */
13668 
13669  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13670  nvarscommon = 0;
13671  commonidxweight = 0;
13672  nvars0minus1 = 0;
13673  diffidx0minus1weight = 0;
13674  nvars1minus0 = 0;
13675  diffidx1minus0weight = 0;
13676  v0 = 0;
13677  v1 = 0;
13678  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13679  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13680  || coefsequal || coefsnegated || tryaggregation) )
13681  {
13682  SCIP_VAR* var;
13683  SCIP_Real val0;
13684  SCIP_Real val1;
13685  int varcmp;
13686 
13687  /* test, if variable appears in only one or in both constraints */
13688  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13689  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13690  else if( v0 < consdata0->nvars )
13691  varcmp = -1;
13692  else
13693  varcmp = +1;
13694 
13695  switch( varcmp )
13696  {
13697  case -1:
13698  /* variable doesn't appear in consdata1 */
13699  var = consdata0->vars[v0];
13700  val0 = consdata0->vals[v0];
13701  val1 = 0.0;
13702  if( tryaggregation )
13703  {
13704  diffidx0minus1[nvars0minus1] = v0;
13705  nvars0minus1++;
13706  diffidx0minus1weight += getVarWeight(var);
13707  }
13708  v0++;
13709  coefsequal = FALSE;
13710  coefsnegated = FALSE;
13711  break;
13712 
13713  case +1:
13714  /* variable doesn't appear in consdata0 */
13715  var = consdata1->vars[v1];
13716  val0 = 0.0;
13717  val1 = consdata1->vals[v1];
13718  if( tryaggregation )
13719  {
13720  diffidx1minus0[nvars1minus0] = v1;
13721  nvars1minus0++;
13722  diffidx1minus0weight += getVarWeight(var);
13723  }
13724  v1++;
13725  coefsequal = FALSE;
13726  coefsnegated = FALSE;
13727  break;
13728 
13729  case 0:
13730  /* variable appears in both constraints */
13731  assert(consdata0->vars[v0] == consdata1->vars[v1]);
13732  var = consdata0->vars[v0];
13733  val0 = consdata0->vals[v0];
13734  val1 = consdata1->vals[v1];
13735  if( tryaggregation )
13736  {
13737  commonidx0[nvarscommon] = v0;
13738  commonidx1[nvarscommon] = v1;
13739  nvarscommon++;
13740  commonidxweight += getVarWeight(var);
13741  }
13742  v0++;
13743  v1++;
13744  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13745  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13746  break;
13747 
13748  default:
13749  SCIPerrorMessage("invalid comparison result\n");
13750  SCIPABORT();
13751  var = NULL;
13752  val0 = 0.0;
13753  val1 = 0.0;
13754  }
13755  assert(var != NULL);
13756 
13757  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13758  if( SCIPisGT(scip, val0, val1) )
13759  {
13760  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13761  {
13762  cons0dominatesrhs = FALSE;
13763  cons1dominateslhs = FALSE;
13764  }
13765  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13766  {
13767  cons0dominateslhs = FALSE;
13768  cons1dominatesrhs = FALSE;
13769  }
13770  }
13771  else if( SCIPisLT(scip, val0, val1) )
13772  {
13773  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13774  {
13775  cons0dominateslhs = FALSE;
13776  cons1dominatesrhs = FALSE;
13777  }
13778  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13779  {
13780  cons0dominatesrhs = FALSE;
13781  cons1dominateslhs = FALSE;
13782  }
13783  }
13784  }
13785 
13786  /* check for disaggregated ranged rows */
13787  if( coefsequal || coefsnegated )
13788  {
13789  SCIP_CONS* consstay;
13790  SCIP_CONS* consdel;
13791 #ifndef NDEBUG
13792  SCIP_CONSDATA* consdatastay;
13793 #endif
13794  SCIP_CONSDATA* consdatadel;
13795  SCIP_Real lhs;
13796  SCIP_Real rhs;
13797  int consinddel;
13798 
13799  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13800  * best left and right hand sides; delete the old constraints afterwards
13801  */
13802  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13803  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13804  SCIPdebugPrintCons(scip, cons0, NULL);
13805  SCIPdebugPrintCons(scip, cons1, NULL);
13806 
13807  if( coefsequal )
13808  {
13809  /* the coefficients of both rows are equal */
13810  lhs = MAX(consdata0->lhs, consdata1->lhs);
13811  rhs = MIN(consdata0->rhs, consdata1->rhs);
13812  }
13813  else
13814  {
13815  /* the coefficients of both rows are negations */
13816  lhs = MAX(consdata0->lhs, -consdata1->rhs);
13817  rhs = MIN(consdata0->rhs, -consdata1->lhs);
13818  }
13819  if( SCIPisFeasLT(scip, rhs, lhs) )
13820  {
13821  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13822  *cutoff = TRUE;
13823  break;
13824  }
13825 
13826  /* check which constraint has to stay;
13827  * changes applied to an upgraded constraint will not be considered in the instance */
13828  if( consdata0->upgraded )
13829  {
13830  assert(!consdata1->upgraded);
13831  consstay = cons1;
13832 #ifndef NDEBUG
13833  consdatastay = consdata1;
13834 #endif
13835 
13836  consdel = cons0;
13837  consdatadel = consdata0;
13838  consinddel = chkind;
13839  }
13840  else
13841  {
13842  consstay = cons0;
13843 #ifndef NDEBUG
13844  consdatastay = consdata0;
13845 #endif
13846 
13847  consdel = cons1;
13848  consdatadel = consdata1;
13849  consinddel = c;
13850  }
13851 
13852  /* update the sides of consstay */
13853  SCIP_CALL( chgLhs(scip, consstay, lhs) );
13854  SCIP_CALL( chgRhs(scip, consstay, rhs) );
13855  if( !consdata0->upgraded )
13856  {
13857  assert(consstay == cons0);
13858  cons0lhs = consdata0->lhs;
13859  cons0rhs = consdata0->rhs;
13860  }
13861 
13862  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13863  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13864 
13865  assert( !consdatastay->upgraded );
13866  /* delete consdel */
13867  SCIP_CALL( SCIPdelCons(scip, consdel) );
13868  conss[consinddel] = NULL;
13869  if( !consdatadel->upgraded )
13870  (*ndelconss)++;
13871  continue;
13872  }
13873 
13874  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13875  * redundant
13876  */
13877  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13878  {
13879  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13880  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13881  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13882  SCIPdebugPrintCons(scip, cons0, NULL);
13883  SCIPdebugPrintCons(scip, cons1, NULL);
13884 
13885  /* check for infeasibility */
13886  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13887  {
13888  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13889  *cutoff = TRUE;
13890  break;
13891  }
13892 
13893  /* remove redundant left hand side */
13894  if( !SCIPisInfinity(scip, -consdata0->lhs) )
13895  {
13896  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13897  cons0lhs = consdata0->lhs;
13898  cons0isequality = FALSE;
13899  if( !consdata0->upgraded )
13900  {
13901  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13902  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13903 
13904  (*nchgsides)++;
13905  }
13906  }
13907  }
13908  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13909  {
13910  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13911  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13912  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13913  SCIPdebugPrintCons(scip, cons1, NULL);
13914  SCIPdebugPrintCons(scip, cons0, NULL);
13915 
13916  /* check for infeasibility */
13917  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13918  {
13919  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13920  *cutoff = TRUE;
13921  break;
13922  }
13923 
13924  /* remove redundant left hand side */
13925  if( !SCIPisInfinity(scip, -consdata1->lhs) )
13926  {
13927  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13928  cons1isequality = FALSE;
13929  if( !consdata1->upgraded )
13930  {
13931  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13932  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13933 
13934  (*nchgsides)++;
13935  }
13936  }
13937  }
13938  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13939  {
13940  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13941  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13942  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13943  SCIPdebugPrintCons(scip, cons0, NULL);
13944  SCIPdebugPrintCons(scip, cons1, NULL);
13945 
13946  /* check for infeasibility */
13947  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13948  {
13949  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13950  *cutoff = TRUE;
13951  break;
13952  }
13953 
13954  /* remove redundant right hand side */
13955  if( !SCIPisInfinity(scip, consdata0->rhs) )
13956  {
13957  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13958  cons0rhs = consdata0->rhs;
13959  cons0isequality = FALSE;
13960  if( !consdata0->upgraded )
13961  {
13962  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13963  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13964 
13965  (*nchgsides)++;
13966  }
13967  }
13968  }
13969  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13970  {
13971  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13972  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13973  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13974  SCIPdebugPrintCons(scip, cons1, NULL);
13975  SCIPdebugPrintCons(scip, cons0, NULL);
13976 
13977  /* check for infeasibility */
13978  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13979  {
13980  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13981  *cutoff = TRUE;
13982  break;
13983  }
13984 
13985  /* remove redundant right hand side */
13986  if( !SCIPisInfinity(scip, consdata1->rhs) )
13987  {
13988  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13989  cons1isequality = FALSE;
13990  if( !consdata1->upgraded )
13991  {
13992  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13993  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13994 
13995  (*nchgsides)++;
13996  }
13997  }
13998  }
13999 
14000  /* check for now redundant constraints */
14001  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
14002  {
14003  /* consdata0 became redundant */
14004  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
14005  SCIP_CALL( SCIPdelCons(scip, cons0) );
14006  conss[chkind] = NULL;
14007  if( !consdata0->upgraded )
14008  {
14009  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14010  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
14011 
14012  (*ndelconss)++;
14013  }
14014  continue;
14015  }
14016  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
14017  {
14018  /* consdata1 became redundant */
14019  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
14020  SCIP_CALL( SCIPdelCons(scip, cons1) );
14021  conss[c] = NULL;
14022  if( !consdata1->upgraded )
14023  {
14024  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14025  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
14026 
14027  (*ndelconss)++;
14028  }
14029  continue;
14030  }
14031 
14032  /* check, if we want to aggregate an (in)equality with an equality:
14033  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
14034  */
14035  if( tryaggregation )
14036  {
14037  SCIP_Bool aggregated;
14038 
14039  assert(consdata0->nvars == nvarscommon + nvars0minus1);
14040  assert(consdata1->nvars == nvarscommon + nvars1minus0);
14041 
14042  aggregated = FALSE;
14043  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
14044  {
14045  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
14046  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
14047  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
14048  nchgcoefs, &aggregated, cutoff) );
14049 
14050  if( *cutoff )
14051  break;
14052 
14053  /* update array of active constraints */
14054  if( aggregated )
14055  {
14056  assert(!SCIPconsIsActive(cons0));
14057  assert(SCIPconsIsActive(cons1));
14058  conss[chkind] = NULL;
14059  }
14060  }
14061  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
14062  {
14063  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
14064  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
14065  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
14066  nchgcoefs, &aggregated, cutoff) );
14067 
14068  if( *cutoff )
14069  break;
14070 
14071  /* update array of active constraints */
14072  if( aggregated )
14073  {
14074  assert(!SCIPconsIsActive(cons1));
14075  assert(SCIPconsIsActive(cons0));
14076  conss[c] = NULL;
14077  }
14078  }
14079  }
14080  }
14081 
14082  /* free temporary memory */
14083  SCIPfreeBufferArray(scip, &diffidx1minus0);
14084  SCIPfreeBufferArray(scip, &diffidx0minus1);
14085  SCIPfreeBufferArray(scip, &commonidx1);
14086  SCIPfreeBufferArray(scip, &commonidx0);
14087 
14088  return SCIP_OKAY;
14089 }
14090 
14091 /** do stuffing presolving on a single constraint */
14092 static
14094  SCIP* scip, /**< SCIP data structure */
14095  SCIP_CONS* cons, /**< linear constraint */
14096  SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14097  SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14098  * constraints using the cheapest variable? */
14099  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14100  int* nfixedvars, /**< pointer to count the total number of fixed variables */
14101  int* nchgbds /**< pointer to count the total number of tightened bounds */
14102  )
14103 {
14104  SCIP_CONSDATA* consdata;
14105  SCIP_Real* ratios;
14106  int* varpos;
14107  SCIP_Bool* swapped;
14108  SCIP_VAR** vars;
14109  SCIP_Real* vals;
14110  SCIP_VAR* var;
14111  SCIP_Real lb;
14113  SCIP_Real minactivity;
14114  SCIP_Real maxactivity;
14115  SCIP_Real maxcondactivity;
14116  SCIP_Real mincondactivity;
14117  SCIP_Real rhs;
14118  SCIP_Real val;
14119  SCIP_Real obj;
14120  SCIP_Real factor;
14121  SCIP_Bool isminacttight;
14122  SCIP_Bool ismaxacttight;
14123  SCIP_Bool isminsettoinfinity;
14124  SCIP_Bool ismaxsettoinfinity;
14125  SCIP_Bool tryfixing;
14126  int nsingletons;
14127  int idx;
14128  int v;
14129  int nvars;
14130 
14131  assert(scip != NULL);
14132  assert(cons != NULL);
14133  assert(nfixedvars != NULL);
14134 
14135  consdata = SCIPconsGetData(cons);
14136 
14137  /* we only want to run for inequalities */
14138  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14139  return SCIP_OKAY;
14140 
14141  if( singlevarstuffing )
14142  {
14143  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
14144  &isminsettoinfinity, &ismaxsettoinfinity);
14145  }
14146  else
14147  {
14148  minactivity = SCIP_INVALID;
14149  maxactivity = SCIP_INVALID;
14150  isminsettoinfinity = FALSE;
14151  ismaxsettoinfinity = FALSE;
14152  }
14153 
14154  /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14155  * the new maxactivity is minus the old minactivity then
14156  */
14157  if( SCIPisInfinity(scip, consdata->rhs) )
14158  {
14159  rhs = -consdata->lhs;
14160  factor = -1.0;
14161  maxactivity = -minactivity;
14162  ismaxsettoinfinity = isminsettoinfinity;
14163  }
14164  else
14165  {
14166  assert(SCIPisInfinity(scip, -consdata->lhs));
14167  rhs = consdata->rhs;
14168  factor = 1.0;
14169  }
14170 
14171  nvars = consdata->nvars;
14172  vars = consdata->vars;
14173  vals = consdata->vals;
14174 
14175  /* check for continuous singletons */
14176  if( singletonstuffing )
14177  {
14178  for( v = 0; v < nvars; ++v )
14179  {
14180  var = vars[v];
14181 
14184  break;
14185  }
14186  }
14187  else
14188  /* we don't want to go into the next block */
14189  v = nvars;
14190 
14191  /* a singleton was found -> perform singleton variable stuffing */
14192  if( v < nvars )
14193  {
14194  assert(singletonstuffing);
14195 
14196  SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14197  SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14198  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14199 
14200  tryfixing = TRUE;
14201  nsingletons = 0;
14202  mincondactivity = 0.0;
14203  maxcondactivity = 0.0;
14204 
14205  for( v = 0; v < nvars; ++v )
14206  {
14207  var = vars[v];
14208  lb = SCIPvarGetLbGlobal(var);
14209  ub = SCIPvarGetUbGlobal(var);
14210  obj = SCIPvarGetObj(var);
14211  val = factor * vals[v];
14212 
14213  assert(!SCIPisZero(scip, val));
14214 
14215  /* the variable is a singleton and continuous */
14218  {
14219  if( SCIPisNegative(scip, obj) && val > 0 )
14220  {
14221  /* case 1: obj < 0 and coef > 0 */
14222  if( SCIPisInfinity(scip, -lb) )
14223  {
14224  tryfixing = FALSE;
14225  break;
14226  }
14227 
14228  maxcondactivity += val * lb;
14229  mincondactivity += val * lb;
14230  swapped[v] = FALSE;
14231  ratios[nsingletons] = obj / val;
14232  varpos[nsingletons] = v;
14233  nsingletons++;
14234  }
14235  else if( SCIPisPositive(scip, obj) && val < 0 )
14236  {
14237  /* case 2: obj > 0 and coef < 0 */
14238  if( SCIPisInfinity(scip, ub) )
14239  {
14240  tryfixing = FALSE;
14241  break;
14242  }
14243  /* multiply column by (-1) to become case 1.
14244  * now bounds are swapped: ub := -lb, lb := -ub
14245  */
14246 
14247  maxcondactivity += val * ub;
14248  mincondactivity += val * ub;
14249  swapped[v] = TRUE;
14250  ratios[nsingletons] = obj / val;
14251  varpos[nsingletons] = v;
14252  nsingletons++;
14253  }
14254  else if( val > 0 )
14255  {
14256  /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14257  * we only consider the lower bound for the constants
14258  */
14259  assert(!SCIPisNegative(scip, obj));
14260 
14261  if( SCIPisInfinity(scip, -lb) )
14262  {
14263  /* maybe unbounded */
14264  tryfixing = FALSE;
14265  break;
14266  }
14267 
14268  maxcondactivity += val * lb;
14269  mincondactivity += val * lb;
14270  }
14271  else
14272  {
14273  /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14274  * we only consider the upper bound for the constants
14275  */
14276  assert(!SCIPisPositive(scip, obj));
14277  assert(val < 0);
14278 
14279  if( SCIPisInfinity(scip, ub) )
14280  {
14281  /* maybe unbounded */
14282  tryfixing = FALSE;
14283  break;
14284  }
14285 
14286  maxcondactivity += val * ub;
14287  mincondactivity += val * ub;
14288  }
14289  }
14290  else
14291  {
14292  /* consider contribution of discrete variables, non-singleton
14293  * continuous variables and variables with more than one lock
14294  */
14295  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14296  {
14297  tryfixing = FALSE;
14298  break;
14299  }
14300 
14301  if( val > 0 )
14302  {
14303  maxcondactivity += val * ub;
14304  mincondactivity += val * lb;
14305  }
14306  else
14307  {
14308  maxcondactivity += val * lb;
14309  mincondactivity += val * ub;
14310  }
14311  }
14312  }
14313  if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14314  {
14315  SCIP_Real delta;
14316  SCIP_Bool tightened;
14317 #ifdef SCIP_DEBUG
14318  int oldnfixedvars = *nfixedvars;
14319  int oldnchgbds = *nchgbds;
14320 #endif
14321 
14322  SCIPsortRealInt(ratios, varpos, nsingletons);
14323 
14324  /* verify which singleton continuous variables can be fixed */
14325  for( v = 0; v < nsingletons; ++v )
14326  {
14327  idx = varpos[v];
14328  var = vars[idx];
14329  val = factor * vals[idx];
14330  lb = SCIPvarGetLbGlobal(var);
14331  ub = SCIPvarGetUbGlobal(var);
14332 
14333  assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14334  assert((val < 0) == swapped[idx]);
14335  val = REALABS(val);
14336 
14337  /* stop fixing if variable bounds are not finite */
14338  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14339  break;
14340 
14343  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14344 
14345  /* calculate the change in the row activities if this variable changes
14346  * its value from its worst to its best bound
14347  */
14348  if( swapped[idx] )
14349  delta = -(lb - ub) * val;
14350  else
14351  delta = (ub - lb) * val;
14352 
14353  assert(!SCIPisNegative(scip, delta));
14354 
14355  if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14356  {
14357  if( swapped[idx] )
14358  {
14359  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14360  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14361  }
14362  else
14363  {
14364  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14365  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14366  }
14367 
14368  if( *cutoff )
14369  break;
14370  if( tightened )
14371  {
14372  (*nfixedvars)++;
14373  }
14374  }
14375  /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14376  * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14377  * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14378  * troubles in case of large bounds.
14379  */
14380  else if( SCIPisLE(scip, rhs, mincondactivity) )
14381  {
14382  if( swapped[idx] )
14383  {
14384  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14385  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14386  }
14387  else
14388  {
14389  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14390  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14391  }
14392 
14393  if( *cutoff )
14394  break;
14395  if( tightened )
14396  {
14397  (*nfixedvars)++;
14398  }
14399  }
14400 
14401  maxcondactivity += delta;
14402  mincondactivity += delta;
14403  }
14404 
14405 #ifdef SCIP_DEBUG
14406  if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14407  {
14408  SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14409  }
14410 #endif
14411  }
14412 
14413  SCIPfreeBufferArray(scip, &swapped);
14414  SCIPfreeBufferArray(scip, &ratios);
14415  SCIPfreeBufferArray(scip, &varpos);
14416  }
14417 
14418  /* perform single-variable stuffing:
14419  * for a linear inequality
14420  * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14421  * with a_i > 0 and objective coefficients c_i < 0,
14422  * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14423  * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14424  * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14425  * is redundant.
14426  * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14427  * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14428  * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14429  * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14430  * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14431  * upper bound.
14432  * Note that the others variables may have downlocks from other constraints, which we do not need to care
14433  * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14434  * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14435  * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14436  * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14437  * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14438  * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14439  * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14440  * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14441  * c_k * ceil((maxactivity - rhs)/val) is still better than
14442  * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14443  * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14444  * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14445  * sign of coefficients in constraint and objective prevent the use of this method.
14446  */
14447  if( singlevarstuffing && !ismaxsettoinfinity )
14448  {
14449  SCIP_Real bestratio = -SCIPinfinity(scip);
14450  SCIP_Real secondbestratio = -SCIPinfinity(scip);
14451  SCIP_Real ratio;
14452  int bestindex = -1;
14453  int bestuplocks = 0;
14454  int bestdownlocks = 1;
14455  int downlocks;
14456  int uplocks;
14457  SCIPdebug( int oldnfixedvars = *nfixedvars; )
14458  SCIPdebug( int oldnchgbds = *nchgbds; )
14459 
14460  /* loop over all variables to identify the best and second-best ratio */
14461  for( v = 0; v < nvars; ++v )
14462  {
14463  var = vars[v];
14464  obj = SCIPvarGetObj(var);
14465  val = factor * vals[v];
14466 
14467  assert(!SCIPisZero(scip, val));
14468 
14469  ratio = obj / val;
14470 
14471  /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14472  if( !SCIPisNegative(scip, ratio) )
14473  {
14474  bestindex = -1;
14475  break;
14476  }
14477 
14478  if( val > 0 )
14479  {
14482  }
14483  else
14484  {
14485  downlocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
14487  }
14488 
14489  /* better ratio, update best candidate
14490  * @todo use some tolerance
14491  * @todo check size of domain and updated ratio for integer variables already?
14492  */
14493  if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14494  || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14495  && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
14496  {
14497  /* best index becomes second-best*/
14498  if( bestindex != -1 )
14499  {
14500  /* second-best index must not have more than 1 uplock */
14501  if( bestuplocks > 1 )
14502  {
14503  bestindex = -1;
14504  break;
14505  }
14506  else
14507  {
14508  secondbestratio = bestratio;
14509  }
14510  }
14511  bestdownlocks = downlocks;
14512  bestuplocks = uplocks;
14513  bestratio = ratio;
14514  bestindex = v;
14515 
14516  /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14517  * if it is not the best, it has too many uplocks -> not applicable
14518  */
14519  if( bestdownlocks > 0 && bestuplocks > 1 )
14520  {
14521  bestindex = -1;
14522  break;
14523  }
14524  }
14525  else
14526  {
14527  /* non-best index must not have more than 1 uplock */
14528  if( uplocks > 1 )
14529  {
14530  bestindex = -1;
14531  break;
14532  }
14533  /* update second-best ratio */
14534  if( ratio > secondbestratio )
14535  {
14536  secondbestratio = ratio;
14537  }
14538  }
14539  }
14540 
14541  /* check if we can apply single variable stuffing */
14542  if( bestindex != -1 && bestdownlocks == 0 )
14543  {
14544  SCIP_Bool tightened = FALSE;
14545  SCIP_Real bounddelta;
14546 
14547  var = vars[bestindex];
14548  obj = SCIPvarGetObj(var);
14549  val = factor * vals[bestindex];
14550  lb = SCIPvarGetLbGlobal(var);
14551  ub = SCIPvarGetUbGlobal(var);
14552  tryfixing = TRUE;
14553 
14554  if( val < 0 )
14555  {
14556  assert(!SCIPisNegative(scip, obj));
14557 
14558  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14559  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14560  {
14561  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14562  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14563  assert(SCIPisPositive(scip, activitydelta));
14564 
14565  tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14566 
14567  bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14568  assert(SCIPisPositive(scip, bounddelta));
14569  }
14570  else
14571  bounddelta = (maxactivity - rhs)/-val;
14572 
14573  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14574 
14575  if( tryfixing )
14576  {
14577  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
14578 
14579  if( SCIPisEQ(scip, lb + bounddelta, ub) )
14580  {
14581  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14582  SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14583  }
14584  else
14585  {
14586  SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14587  SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14588  }
14589  }
14590  }
14591  else
14592  {
14593  assert(!SCIPisPositive(scip, obj));
14594 
14595  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14596  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14597  {
14598  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14599  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14600  assert(SCIPisPositive(scip, activitydelta));
14601 
14602  tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14603 
14604  bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14605  assert(SCIPisPositive(scip, bounddelta));
14606  }
14607  else
14608  bounddelta = (maxactivity - rhs)/val;
14609 
14610  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14611 
14612  if( tryfixing )
14613  {
14614  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
14615 
14616  if( SCIPisEQ(scip, ub - bounddelta, lb) )
14617  {
14618  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14619  SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14620  }
14621  else
14622  {
14623  SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14624  SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14625  }
14626  }
14627  }
14628 
14629  if( *cutoff )
14630  return SCIP_OKAY;
14631  if( tightened )
14632  {
14633  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14634  ++(*nfixedvars);
14635  else
14636  ++(*nchgbds);
14637 
14638  SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14639  for( v = 0; v < nvars; ++v )
14640  {
14641  SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14642  SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14645  SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14646  }
14647  SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14648 
14649  for( v = 0; v < nvars; ++v )
14650  {
14651  if( v == bestindex )
14652  continue;
14653 
14654  if( factor * vals[v] < 0 )
14655  {
14656  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14657  SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14658  SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14659  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14660  }
14661  else
14662  {
14663  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14664  SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14665  SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14666  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14667  }
14668 
14669  if( *cutoff )
14670  return SCIP_OKAY;
14671  if( tightened )
14672  ++(*nfixedvars);
14673  }
14674  SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14675  }
14676  }
14677  }
14678 
14679  return SCIP_OKAY;
14680 }
14681 
14682 /** applies full dual presolving on variables that only appear in linear constraints */
14683 static
14685  SCIP* scip, /**< SCIP data structure */
14686  SCIP_CONS** conss, /**< constraint set */
14687  int nconss, /**< number of constraints */
14688  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14689  int* nchgbds /**< pointer to count the number of bound changes */
14690  )
14691 {
14692  SCIP_Real* redlb;
14693  SCIP_Real* redub;
14694  int* nlocksdown;
14695  int* nlocksup;
14696  SCIP_Bool* isimplint;
14697  SCIP_VAR** origvars;
14698  SCIP_VAR** vars;
14699  SCIP_VAR** conscontvars;
14700  int nvars;
14701  int nbinvars;
14702  int nintvars;
14703  int ncontvars;
14704  int v;
14705  int c;
14706 
14707  /* we calculate redundancy bounds with the following meaning:
14708  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14709  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14710  * then:
14711  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14712  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14713  */
14714 
14715  /* Additionally, we detect continuous variables that are implicitly integral.
14716  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14717  * and all constraints (including the bounds as trivial constraints) in which:
14718  * c_j > 0: the variable is down-locked,
14719  * c_j < 0: the variable is up-locked,
14720  * c_j = 0: the variable appears
14721  * have, apart from j, only integer variables with integral coefficients and integral sides.
14722  * This is because then, the value of the variable is either determined by one of its bounds or
14723  * by one of these constraints, and in all cases, the value of the variable is integral.
14724  */
14725 
14726  assert(scip != NULL);
14727  assert(nconss == 0 || conss != NULL);
14728  assert(nchgbds != NULL);
14729  assert(!SCIPinProbing(scip));
14730 
14731  /* get active variables */
14732  nvars = SCIPgetNVars(scip);
14733  origvars = SCIPgetVars(scip);
14734 
14735  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14736  nbinvars = SCIPgetNBinVars(scip);
14737  if( nbinvars == nvars )
14738  return SCIP_OKAY;
14739 
14740  /* get number of continuous variables */
14741  ncontvars = SCIPgetNContVars(scip);
14742  nintvars = nvars - ncontvars;
14743 
14744  /* copy the variable array since this array might change during the curse of this algorithm */
14745  nvars = nvars - nbinvars;
14746  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14747 
14748  /* allocate temporary memory */
14749  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14750  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14751  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14752  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14753  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14754  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14755 
14756  /* initialize redundancy bounds */
14757  for( v = 0; v < nvars; ++v )
14758  {
14759  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14760  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14761  redub[v] = SCIPvarGetUbGlobal(vars[v]);
14762  }
14763  BMSclearMemoryArray(nlocksdown, nvars);
14764  BMSclearMemoryArray(nlocksup, nvars);
14765 
14766  /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14767  * We better not use SCIPisFeasIntegral() in these checks.
14768  */
14769  for( v = 0; v < ncontvars; v++ )
14770  {
14771  SCIP_VAR* var;
14772  SCIP_Real obj;
14773  SCIP_Real lb;
14774  SCIP_Real ub;
14775 
14776  var = vars[v + nintvars - nbinvars];
14777  lb = SCIPvarGetLbGlobal(var);
14778  ub = SCIPvarGetUbGlobal(var);
14779 
14780  obj = SCIPvarGetObj(var);
14781  if( SCIPisZero(scip, obj) )
14782  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14783  else
14784  {
14785  if( SCIPisPositive(scip, obj) )
14786  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14787  else
14788  {
14789  assert(SCIPisNegative(scip, obj));
14790  isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14791  }
14792  }
14793  }
14794 
14795  /* scan all constraints */
14796  for( c = 0; c < nconss; ++c )
14797  {
14798  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14799  * part of checked disjunctions)
14800  */
14801  if( SCIPconsIsLocked(conss[c]) )
14802  {
14803  SCIP_CONSDATA* consdata;
14804  SCIP_Bool lhsexists;
14805  SCIP_Bool rhsexists;
14806  SCIP_Bool hasimpliedpotential;
14807  SCIP_Bool integralcoefs;
14808  int nlockspos;
14809  int contvarpos;
14810  int nconscontvars;
14811  int i;
14812 
14813  consdata = SCIPconsGetData(conss[c]);
14814  assert(consdata != NULL);
14815 
14816  /* get number of times the constraint was locked */
14817  nlockspos = SCIPconsGetNLocksPos(conss[c]);
14818 
14819  /* we do not want to include constraints with locked negation (this would be too weird) */
14820  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14821  {
14822  /* mark all continuous variables as not being implicit integral */
14823  for( i = 0; i < consdata->nvars; ++i )
14824  {
14825  SCIP_VAR* var;
14826 
14827  var = consdata->vars[i];
14829  {
14830  int contv;
14831  contv = SCIPvarGetProbindex(var) - nintvars;
14832  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14833  isimplint[contv] = FALSE;
14834  }
14835  }
14836  continue;
14837  }
14838 
14839  /* check for existing sides */
14840  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14841  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14842 
14843  /* count locks and update redundancy bounds */
14844  contvarpos = -1;
14845  nconscontvars = 0;
14846  hasimpliedpotential = FALSE;
14847  integralcoefs = !SCIPconsIsModifiable(conss[c]);
14848 
14849  for( i = 0; i < consdata->nvars; ++i )
14850  {
14851  SCIP_VAR* var;
14852  SCIP_Real val;
14853  SCIP_Real minresactivity;
14854  SCIP_Real maxresactivity;
14855  SCIP_Real newredlb;
14856  SCIP_Real newredub;
14857  SCIP_Bool ismintight;
14858  SCIP_Bool ismaxtight;
14859  SCIP_Bool isminsettoinfinity;
14860  SCIP_Bool ismaxsettoinfinity;
14861  int arrayindex;
14862 
14863  var = consdata->vars[i];
14864  val = consdata->vals[i];
14865 
14866  /* check if still all integer variables have integral coefficients */
14867  if( SCIPvarIsIntegral(var) )
14868  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14869 
14870  /* we do not need to process binary variables */
14871  if( SCIPvarIsBinary(var) )
14872  continue;
14873 
14874  if( SCIPconsIsModifiable(conss[c]) )
14875  {
14876  minresactivity = -SCIPinfinity(scip);
14877  maxresactivity = SCIPinfinity(scip);
14878  isminsettoinfinity = TRUE;
14879  ismaxsettoinfinity = TRUE;
14880  }
14881  else
14882  {
14883  /* calculate residual activity bounds if variable would be fixed to zero */
14884  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14885  &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
14886 
14887  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14888  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14889  * This is needed, because we do not want to rely on relaxed finite resactivities.
14890  */
14891  assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
14892 
14893  /* check minresactivity for reliability */
14894  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14895  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14896 
14897  /* check maxresactivity for reliability */
14898  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14899  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14900  }
14901 
14902  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14903 
14904  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14905 
14906  newredlb = redlb[arrayindex];
14907  newredub = redub[arrayindex];
14908  if( val > 0.0 )
14909  {
14910  if( lhsexists )
14911  {
14912  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14913  nlocksdown[arrayindex] += nlockspos;
14914  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14915  }
14916  if( rhsexists )
14917  {
14918  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14919  nlocksup[arrayindex] += nlockspos;
14920  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14921  }
14922  }
14923  else
14924  {
14925  if( lhsexists )
14926  {
14927  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14928  nlocksup[arrayindex] += nlockspos;
14929  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14930  }
14931  if( rhsexists )
14932  {
14933  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14934  nlocksdown[arrayindex] += nlockspos;
14935  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14936  }
14937  }
14938 
14939  /* if the variable is integer, we have to round the value to the next integral value */
14940  if( SCIPvarIsIntegral(var) )
14941  {
14942  if( !SCIPisInfinity(scip, newredlb) )
14943  newredlb = SCIPceil(scip, newredlb);
14944  if( !SCIPisInfinity(scip, -newredub) )
14945  newredub = SCIPfloor(scip, newredub);
14946  }
14947 
14948  /* update redundancy bounds */
14949  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14950  redub[arrayindex] = MIN(redub[arrayindex], newredub);
14951 
14952  /* collect the continuous variables of the constraint */
14954  {
14955  int contv;
14956 
14957  assert(nconscontvars < ncontvars);
14958  contvarpos = i;
14959  conscontvars[nconscontvars] = var;
14960  nconscontvars++;
14961 
14962  contv = SCIPvarGetProbindex(var) - nintvars;
14963  assert(0 <= contv && contv < ncontvars);
14964  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14965  }
14966  }
14967 
14968  /* update implicit integer status of continuous variables */
14969  if( hasimpliedpotential )
14970  {
14971  if( nconscontvars > 1 || !integralcoefs )
14972  {
14973  /* there is more than one continuous variable or the integer variables have fractional coefficients:
14974  * none of the continuous variables is implicit integer
14975  */
14976  for( i = 0; i < nconscontvars; i++ )
14977  {
14978  int contv;
14979  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14980  assert(0 <= contv && contv < ncontvars);
14981  isimplint[contv] = FALSE;
14982  }
14983  }
14984  else
14985  {
14986  SCIP_VAR* var;
14987  SCIP_Real val;
14988  SCIP_Real absval;
14989  int contv;
14990 
14991  /* there is exactly one continuous variable and the integer variables have integral coefficients:
14992  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14993  * side(s) of the constraint is integral
14994  */
14995  assert(nconscontvars == 1);
14996  assert(0 <= contvarpos && contvarpos < consdata->nvars);
14997  var = consdata->vars[contvarpos];
14998  val = consdata->vals[contvarpos];
14999  contv = SCIPvarGetProbindex(var) - nintvars;
15000  assert(0 <= contv && contv < ncontvars);
15001  assert(isimplint[contv]);
15002 
15003  absval = REALABS(val);
15004  if( !SCIPisEQ(scip, absval, 1.0) )
15005  isimplint[contv] = FALSE;
15006  else
15007  {
15008  SCIP_Real obj;
15009 
15010  obj = SCIPvarGetObj(var);
15011  if( obj * val >= 0.0 && lhsexists )
15012  {
15013  /* the variable may be blocked by the constraint's left hand side */
15014  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
15015  }
15016  if( obj * val <= 0.0 && rhsexists )
15017  {
15018  /* the variable may be blocked by the constraint's left hand side */
15019  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
15020  }
15021  }
15022  }
15023  }
15024  }
15025  }
15026 
15027  /* check if any bounds can be tightened due to optimality */
15028  for( v = 0; v < nvars; ++v )
15029  {
15030  SCIP_VAR* var;
15031  SCIP_Real obj;
15032  SCIP_Bool infeasible;
15033  SCIP_Bool tightened;
15034 
15035  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
15036  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15037  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15038 
15039  var = vars[v];
15040  obj = SCIPvarGetObj(var);
15041  if( !SCIPisPositive(scip, -obj) )
15042  {
15043  /* making the variable as small as possible does not increase the objective:
15044  * check if all down locks of the variables are due to linear constraints;
15045  * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
15046  * constraints redundant is huge, we better do nothing for numerical reasons
15047  */
15048  if( ( SCIPisPositive(scip, obj) || SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) || !SCIPisInfinity(scip, -SCIPvarGetLbGlobal(var)) )
15049  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15050  && !SCIPisHugeValue(scip, -redlb[v])
15051  && redlb[v] < SCIPvarGetUbGlobal(var) )
15052  {
15053  SCIP_Real ub;
15054 
15055  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
15056  * -> tighten upper bound to x_v <= redlb[v]
15057  */
15058  SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
15060  redlb[v]);
15061  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
15062  assert(!infeasible);
15063 
15064  ub = SCIPvarGetUbGlobal(var);
15065  redub[v] = MIN(redub[v], ub);
15066  if( tightened )
15067  (*nchgbds)++;
15068  }
15069  }
15070  if( !SCIPisPositive(scip, obj) )
15071  {
15072  /* making the variable as large as possible does not increase the objective:
15073  * check if all up locks of the variables are due to linear constraints;
15074  * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
15075  * constraints redundant is huge, we better do nothing for numerical reasons
15076  */
15077  if( ( SCIPisPositive(scip, -obj) || SCIPisPositive(scip, -SCIPvarGetLbGlobal(var)) || !SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)) )
15078  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
15079  && !SCIPisHugeValue(scip, redub[v])
15080  && redub[v] > SCIPvarGetLbGlobal(var) )
15081  {
15082  SCIP_Real lb;
15083 
15084  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
15085  * -> tighten lower bound to x_v >= redub[v]
15086  */
15087  SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
15089  redub[v]);
15090  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15091  assert(!infeasible);
15092 
15093  lb = SCIPvarGetLbGlobal(var);
15094  redlb[v] = MAX(redlb[v], lb);
15095  if( tightened )
15096  (*nchgbds)++;
15097  }
15098  }
15099  }
15100 
15101  /* upgrade continuous variables to implicit integers */
15102  for( v = nintvars - nbinvars; v < nvars; ++v )
15103  {
15104  SCIP_VAR* var;
15105  SCIP_Bool infeasible;
15106 
15107  var = vars[v];
15108  assert(var != NULL);
15109 
15110  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
15111  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15112  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15113  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15114 
15115  /* we can only conclude implicit integrality if the variable appears in no other constraint */
15116  if( isimplint[v - nintvars + nbinvars]
15117  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15118  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15119  {
15120  /* since we locally copied the variable array we can change the variable type immediately */
15121  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15122 
15123  if( infeasible )
15124  {
15125  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15126  *cutoff = TRUE;
15127 
15128  break;
15129  }
15130 
15131  SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15133  }
15134  }
15135 
15136  /* free temporary memory */
15137  SCIPfreeBufferArray(scip, &conscontvars);
15138  SCIPfreeBufferArray(scip, &isimplint);
15139  SCIPfreeBufferArray(scip, &nlocksup);
15140  SCIPfreeBufferArray(scip, &nlocksdown);
15141  SCIPfreeBufferArray(scip, &redub);
15142  SCIPfreeBufferArray(scip, &redlb);
15143 
15144  SCIPfreeBufferArray(scip, &vars);
15145 
15146  return SCIP_OKAY;
15147 }
15148 
15149 /** helper function to enforce constraints */
15150 static
15152  SCIP* scip, /**< SCIP data structure */
15153  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15154  SCIP_CONS** conss, /**< constraints to process */
15155  int nconss, /**< number of constraints */
15156  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15157  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15158  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15159  )
15160 {
15161  SCIP_CONSHDLRDATA* conshdlrdata;
15162  SCIP_Bool checkrelmaxabs;
15163  SCIP_Bool violated;
15164  SCIP_Bool cutoff = FALSE;
15165  int c;
15166 
15167  assert(scip != NULL);
15168  assert(conshdlr != NULL);
15169  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15170  assert(result != NULL);
15171 
15172  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15173  assert(conshdlrdata != NULL);
15174 
15175  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15176 
15177  SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15178 
15179  /* check for violated constraints
15180  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15181  */
15182  *result = SCIP_FEASIBLE;
15183 
15184  /* check all useful linear constraints for feasibility */
15185  for( c = 0; c < nusefulconss; ++c )
15186  {
15187  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15188 
15189  if( violated )
15190  {
15191  /* insert LP row as cut */
15192  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15193  if ( cutoff )
15194  *result = SCIP_CUTOFF;
15195  else
15196  *result = SCIP_SEPARATED;
15197  }
15198  }
15199 
15200  /* check all obsolete linear constraints for feasibility */
15201  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15202  {
15203  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15204 
15205  if( violated )
15206  {
15207  /* insert LP row as cut */
15208  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15209  if ( cutoff )
15210  *result = SCIP_CUTOFF;
15211  else
15212  *result = SCIP_SEPARATED;
15213  }
15214  }
15215 
15216  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15217 
15218  return SCIP_OKAY;
15219 }
15220 
15221 /** adds symmetry information of constraint to a symmetry detection graph */
15222 static
15224  SCIP* scip, /**< SCIP pointer */
15225  SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15226  SCIP_CONS* cons, /**< constraint */
15227  SYM_GRAPH* graph, /**< symmetry detection graph */
15228  SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15229  )
15230 {
15231  SCIP_CONSDATA* consdata;
15232  SCIP_VAR** vars;
15233  SCIP_Real* vals;
15234  SCIP_Real constant = 0.0;
15235  SCIP_Real lhs;
15236  SCIP_Real rhs;
15237  int nlocvars;
15238  int nvars;
15239  int i;
15240 
15241  assert(scip != NULL);
15242  assert(cons != NULL);
15243  assert(graph != NULL);
15244  assert(success != NULL);
15245 
15246  consdata = SCIPconsGetData(cons);
15247  assert(consdata != NULL);
15248 
15249  /* get active variables of the constraint */
15250  nvars = SCIPgetNVars(scip);
15251  nlocvars = consdata->nvars;
15252 
15253  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
15254  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
15255 
15256  for( i = 0; i < nlocvars; ++i )
15257  {
15258  vars[i] = consdata->vars[i];
15259  vals[i] = consdata->vals[i];
15260  }
15261 
15262  SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15263  lhs = consdata->lhs - constant;
15264  rhs = consdata->rhs - constant;
15265 
15266  /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15267  * of the same constraint are rated as equal
15268  */
15269  if ( SCIPisInfinity(scip, rhs) )
15270  {
15271  SCIP_Real tmp;
15272  assert(!SCIPisInfinity(scip, -lhs));
15273 
15274  for( i = 0; i < nlocvars; ++i )
15275  vals[i] *= -1;
15276  tmp = rhs;
15277  rhs = -lhs;
15278  lhs = -tmp;
15279  }
15280 
15281  SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
15282  cons, lhs, rhs, success) );
15283 
15284  SCIPfreeBufferArray(scip, &vals);
15285  SCIPfreeBufferArray(scip, &vars);
15286 
15287  return SCIP_OKAY;
15288 }
15289 
15290 /*
15291  * Callback methods of constraint handler
15292  */
15293 
15294 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
15295 static
15296 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15297 { /*lint --e{715}*/
15298  assert(scip != NULL);
15299  assert(conshdlr != NULL);
15300  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15301 
15302  /* call inclusion method of constraint handler */
15304 
15305  *valid = TRUE;
15306 
15307  return SCIP_OKAY;
15308 }
15309 
15310 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15311 static
15312 SCIP_DECL_CONSFREE(consFreeLinear)
15313 { /*lint --e{715}*/
15314  SCIP_CONSHDLRDATA* conshdlrdata;
15316  assert(scip != NULL);
15317  assert(conshdlr != NULL);
15318  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15319 
15320  /* free constraint handler data */
15321  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15322  assert(conshdlrdata != NULL);
15323 
15324  conshdlrdataFree(scip, &conshdlrdata);
15325 
15326  SCIPconshdlrSetData(conshdlr, NULL);
15327 
15328  return SCIP_OKAY;
15329 }
15330 
15332 /** initialization method of constraint handler (called after problem was transformed) */
15333 static
15334 SCIP_DECL_CONSINIT(consInitLinear)
15335 {
15336  SCIP_CONSHDLRDATA* conshdlrdata;
15337  int c;
15338 
15339  assert(scip != NULL);
15340 
15341  /* check for event handler */
15342  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15343  assert(conshdlrdata != NULL);
15344  assert(conshdlrdata->eventhdlr != NULL);
15345  assert(nconss == 0 || conss != NULL);
15346 
15347  conshdlrdata->naddconss = 0;
15348 
15349  /* catch events for the constraints */
15350  for( c = 0; c < nconss; ++c )
15351  {
15352  /* catch all events */
15353  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15354  }
15355 
15356  return SCIP_OKAY;
15357 }
15358 
15359 
15360 /** deinitialization method of constraint handler (called before transformed problem is freed) */
15361 static
15362 SCIP_DECL_CONSEXIT(consExitLinear)
15363 {
15364  SCIP_CONSHDLRDATA* conshdlrdata;
15365  int c;
15366 
15367  assert(scip != NULL);
15368 
15369  /* check for event handler */
15370  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15371  assert(conshdlrdata != NULL);
15372  assert(conshdlrdata->eventhdlr != NULL);
15373 
15374  /* drop events for the constraints */
15375  for( c = nconss - 1; c >= 0; --c )
15376  {
15377  SCIP_CONSDATA* consdata;
15378 
15379  consdata = SCIPconsGetData(conss[c]);
15380  assert(consdata != NULL);
15382  if( consdata->eventdata != NULL )
15383  {
15384  /* drop all events */
15385  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15386  assert(consdata->eventdata == NULL);
15387  }
15388  }
15389 
15390  return SCIP_OKAY;
15391 }
15392 
15393 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15394 static
15396  SCIP* scip, /**< SCIP data structure */
15397  SCIP_Real lhs, /**< left hand side */
15398  SCIP_Real rhs /**< right hand side */
15399  )
15400 {
15401  assert(scip != NULL);
15402 
15403  return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15404 }
15405 
15406 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15407 static
15409  SCIP* scip, /**< SCIP data structure */
15410  SCIP_Real x /**< value */
15411  )
15412 {
15413  assert(scip != NULL);
15415  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15416 }
15417 
15418 /** performs linear constraint type classification as used for MIPLIB
15419  *
15420  * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15421  *
15422  * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15423  * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15424  * Similarly, if specialized constraints were created through the API, these are currently not present.
15425  */
15427  SCIP* scip, /**< SCIP data structure */
15428  SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15429  )
15430 {
15431  int c;
15432  SCIP_CONSHDLR* conshdlr;
15433  SCIP_CONS** conss;
15434  int nconss;
15435 
15436  assert(scip != NULL);
15437  assert(linconsstats != NULL);
15438  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15439  assert(conshdlr != NULL);
15440 
15441  if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
15442  {
15443  conss = SCIPgetConss(scip);
15444  nconss = SCIPgetNConss(scip);
15445  }
15446  else
15447  {
15448  conss = SCIPconshdlrGetConss(conshdlr);
15449  nconss = SCIPconshdlrGetNConss(conshdlr);
15450  }
15451 
15452  /* reset linear constraint type classification */
15453  SCIPlinConsStatsReset(linconsstats);
15454 
15455  /* loop through all constraints */
15456  for( c = 0; c < nconss; c++ )
15457  {
15458  SCIP_CONS* cons;
15459  SCIP_CONSDATA* consdata;
15460  SCIP_Real lhs;
15461  SCIP_Real rhs;
15462  int i;
15463 
15464  /* get constraint */
15465  cons = conss[c];
15466  assert(cons != NULL);
15467 
15468  /* skip constraints that are not handled by the constraint handler */
15469  if( SCIPconsGetHdlr(cons) != conshdlr )
15470  continue;
15471 
15472  /* get constraint data */
15473  consdata = SCIPconsGetData(cons);
15474  assert(consdata != NULL);
15475  rhs = consdata->rhs;
15476  lhs = consdata->lhs;
15477 
15478  /* merge multiples and delete variables with zero coefficient */
15479  SCIP_CALL( mergeMultiples(scip, cons) );
15480  for( i = 0; i < consdata->nvars; i++ )
15481  {
15482  assert(!SCIPisZero(scip, consdata->vals[i]));
15483  }
15484 
15485  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15486  if( consdata->nvars == 0 )
15487  {
15488  SCIPdebugMsg(scip, "classified as EMPTY: ");
15489  SCIPdebugPrintCons(scip, cons, NULL);
15491 
15492  continue;
15493  }
15494 
15495  /* is constraint of type SCIP_CONSTYPE_FREE? */
15496  if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15497  {
15498  SCIPdebugMsg(scip, "classified as FREE: ");
15499  SCIPdebugPrintCons(scip, cons, NULL);
15501 
15502  continue;
15503  }
15504 
15505  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15506  if( consdata->nvars == 1 )
15507  {
15508  SCIPdebugMsg(scip, "classified as SINGLETON: ");
15509  SCIPdebugPrintCons(scip, cons, NULL);
15510  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15511 
15512  continue;
15513  }
15514 
15515  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15516  if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15517  {
15518  SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15519  SCIPdebugPrintCons(scip, cons, NULL);
15521 
15522  continue;
15523  }
15524 
15525  /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15526  if( consdata->nvars == 2 )
15527  {
15528  SCIP_LINCONSTYPE constype;
15529 
15530  /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15531  if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15532  && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15533  {
15534  constype = SCIP_LINCONSTYPE_PRECEDENCE;
15535  SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15536  }
15537  else
15538  {
15539  constype = SCIP_LINCONSTYPE_VARBOUND;
15540  SCIPdebugMsg(scip, "classified as VARBOUND: ");
15541  }
15542  SCIPdebugPrintCons(scip, cons, NULL);
15543 
15544  SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15545 
15546  continue;
15547  }
15548 
15549  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15550  {
15551  SCIP_Real scale;
15552  SCIP_Real b;
15553  SCIP_Bool unmatched;
15554  int nnegbinvars;
15555 
15556  unmatched = FALSE;
15557  nnegbinvars = 0;
15558 
15559  scale = REALABS(consdata->vals[0]);
15560 
15561  /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15562  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15563  {
15564  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15565  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15566  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15567  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15568 
15569  if( consdata->vals[i] < 0.0 )
15570  nnegbinvars++;
15571  }
15572 
15573  if( !unmatched )
15574  {
15575  if( SCIPisEQ(scip, lhs, rhs) )
15576  {
15577  b = rhs/scale + nnegbinvars;
15578  if( SCIPisEQ(scip, 1.0, b) )
15579  {
15580  SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15581  SCIPdebugPrintCons(scip, cons, NULL);
15583 
15584  continue;
15585  }
15586  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15587  {
15588  SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15589  SCIPdebugPrintCons(scip, cons, NULL);
15591 
15592  continue;
15593  }
15594  }
15595 
15596  /* compute right hand side divided by scale */
15597  if( !SCIPisInfinity(scip, rhs) )
15598  b = rhs/scale + nnegbinvars;
15599  else
15600  b = SCIPinfinity(scip);
15601 
15602  if( SCIPisEQ(scip, 1.0, b) )
15603  {
15604  SCIPdebugMsg(scip, "classified as SETPACKING: ");
15605  SCIPdebugPrintCons(scip, cons, NULL);
15607 
15608  /* relax right hand side to prevent further classifications */
15609  rhs = SCIPinfinity(scip);
15610  }
15611  else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15612  {
15613  SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15614  SCIPdebugPrintCons(scip, cons, NULL);
15615 
15617 
15618  /* relax right hand side to prevent further classifications */
15619  rhs = SCIPinfinity(scip);
15620  }
15621 
15622  if( !SCIPisInfinity(scip, lhs) )
15623  b = lhs/scale + nnegbinvars;
15624  else
15625  b = SCIPinfinity(scip);
15626 
15627  if( SCIPisEQ(scip, 1.0, b) )
15628  {
15629  SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15630  SCIPdebugPrintCons(scip, cons, NULL);
15632 
15633  /* relax left hand side to prevent further classifications */
15634  lhs = -SCIPinfinity(scip);
15635  }
15636 
15637  /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15638  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15639  continue;
15640  }
15641  }
15642 
15643  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15644  /* @todo If coefficients or rhs are not integral, we currently do not check
15645  * if the constraint could be scaled (finitely), such that they are.
15646  */
15647  {
15648  SCIP_Real b;
15649  SCIP_Bool unmatched;
15650 
15651  b = rhs;
15652  unmatched = FALSE;
15653  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15654  {
15655  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15656  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15657  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15658  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15659 
15660  if( SCIPisNegative(scip, consdata->vals[i]) )
15661  b -= consdata->vals[i];
15662  }
15663  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15664 
15665  if( !unmatched )
15666  {
15667  if( SCIPisEQ(scip, lhs, rhs) )
15668  {
15669  SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15670  SCIPdebugPrintCons(scip, cons, NULL);
15671 
15673 
15674  continue;
15675  }
15676  else
15677  {
15678  SCIP_Bool matched;
15679 
15680  matched = FALSE;
15681  for( i = 0; i < consdata->nvars && !matched; i++ )
15682  {
15683  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15684  }
15685 
15686  SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15687  SCIPdebugPrintCons(scip, cons, NULL);
15689  }
15690 
15691  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15692  if( SCIPisInfinity(scip, -lhs) )
15693  continue;
15694  else
15695  rhs = SCIPinfinity(scip);
15696  }
15697  }
15698 
15699  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15700  {
15701  SCIP_Real b;
15702  SCIP_Bool unmatched;
15703 
15704  unmatched = FALSE;
15705 
15706  b = rhs;
15707  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15708 
15709  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15710  {
15711  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15712  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15713  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15714  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15715  }
15716 
15717  if( !unmatched )
15718  {
15719  SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15720  SCIPdebugPrintCons(scip, cons, NULL);
15722 
15723  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15724  if( SCIPisInfinity(scip, -lhs) )
15725  continue;
15726  else
15727  rhs = SCIPinfinity(scip);
15728  }
15729  }
15730 
15731  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15732  {
15733  SCIP_Bool unmatched;
15734 
15735  unmatched = FALSE;
15736  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15737  {
15738  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15739  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15740  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15741  unmatched = TRUE;
15742  }
15743 
15744  if( !unmatched )
15745  {
15746  SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15747  SCIPdebugPrintCons(scip, cons, NULL);
15748  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15749 
15750  continue;
15751  }
15752  }
15753 
15754  /* no special structure detected */
15755  SCIPdebugMsg(scip, "classified as GENERAL: ");
15756  SCIPdebugPrintCons(scip, cons, NULL);
15757  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15758  }
15759 
15760  return SCIP_OKAY;
15761 }
15762 
15763 
15764 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15765 static
15766 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15767 { /*lint --e{715}*/
15768  int c;
15769 #ifdef SCIP_STATISTIC
15770  SCIP_CONSHDLRDATA* conshdlrdata;
15771  int ngoodconss;
15772  int nallconss;
15773 #endif
15774 
15775  /* delete all linear constraints that were upgraded to a more specific constraint type;
15776  * make sure, only active variables remain in the remaining constraints
15777  */
15778  assert(scip != NULL);
15779 
15780 #ifdef SCIP_STATISTIC
15781  /* count number of well behaved linear constraints */
15782  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15783  assert(conshdlrdata != NULL);
15784 
15785  ngoodconss = 0;
15786  nallconss = 0;
15787 
15788  for( c = 0; c < nconss; ++c )
15789  {
15790  SCIP_CONSDATA* consdata;
15791 
15792  if( SCIPconsIsDeleted(conss[c]) )
15793  continue;
15794 
15795  consdata = SCIPconsGetData(conss[c]);
15796  assert(consdata != NULL);
15797 
15798  if( consdata->upgraded )
15799  continue;
15800 
15801  nallconss++;
15802 
15803  consdataRecomputeMaxActivityDelta(scip, consdata);
15804 
15805  if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15806  ngoodconss++;
15807  }
15808  if( nallconss )
15809  {
15810  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15811  }
15812 #endif
15813 
15814  for( c = 0; c < nconss; ++c )
15815  {
15816  SCIP_CONSDATA* consdata;
15817 
15818  if( SCIPconsIsDeleted(conss[c]) )
15819  continue;
15820 
15821  consdata = SCIPconsGetData(conss[c]);
15822  assert(consdata != NULL);
15823 
15824  if( consdata->upgraded )
15825  {
15826  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15827  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15828  */
15829  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15830  }
15831  else
15832  {
15833  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15834  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15835  }
15836  }
15837 
15838  return SCIP_OKAY;
15839 }
15840 
15841 /** solving process initialization method of constraint handler */
15842 static
15843 SCIP_DECL_CONSINITSOL(consInitsolLinear)
15844 { /*lint --e{715}*/
15845  /* add nlrow representation to NLP, if NLP had been constructed */
15846  if( SCIPisNLPConstructed(scip) )
15847  {
15848  int c;
15849  for( c = 0; c < nconss; ++c )
15850  {
15851  SCIP_CALL( addNlrow(scip, conss[c]) );
15852  }
15853  }
15854 
15855  return SCIP_OKAY;
15856 }
15857 
15858 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15859 static
15860 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15861 { /*lint --e{715}*/
15862  int c;
15863 
15864  assert(scip != NULL);
15865 
15866  /* release the rows and nlrows of all constraints */
15867  for( c = 0; c < nconss; ++c )
15868  {
15869  SCIP_CONSDATA* consdata;
15870 
15871  consdata = SCIPconsGetData(conss[c]);
15872  assert(consdata != NULL);
15873 
15874  if( consdata->row != NULL )
15875  {
15876  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15877  }
15878 
15879  if( consdata->nlrow != NULL )
15880  {
15881  SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15882  }
15883  }
15884 
15885  /* if this is a restart, convert cutpool rows into linear constraints */
15886  if( restart )
15887  {
15888  int ncutsadded;
15889 
15890  ncutsadded = 0;
15891 
15892  /* create out of all active cuts in cutpool linear constraints */
15893  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15894 
15895  if( ncutsadded > 0 )
15896  {
15898  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15899  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15900  * line correctly
15901  */
15903  }
15904  }
15905 
15906  return SCIP_OKAY;
15907 }
15908 
15909 
15910 /** constraint activation notification method of constraint handler */
15911 static
15912 SCIP_DECL_CONSACTIVE(consActiveLinear)
15913 { /*lint --e{715}*/
15914  assert(cons != NULL);
15915 
15916  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisNLPConstructed(scip) )
15917  {
15918  SCIP_CALL( addNlrow(scip, cons) );
15919  }
15920 
15921  return SCIP_OKAY;
15922 }
15923 
15924 /** constraint deactivation notification method of constraint handler */
15925 static
15926 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15927 { /*lint --e{715}*/
15928  SCIP_CONSDATA* consdata;
15929 
15930  assert(scip != NULL);
15931  assert(conshdlr != NULL);
15932  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15933  assert(cons != NULL );
15934 
15935  /* get constraint data */
15936  consdata = SCIPconsGetData(cons);
15937  assert(consdata != NULL);
15938 
15939  if( SCIPconsIsDeleted(cons) )
15940  {
15941  SCIP_CONSHDLRDATA* conshdlrdata;
15942 
15943  /* check for event handler */
15944  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15945  assert(conshdlrdata != NULL);
15946  assert(conshdlrdata->eventhdlr != NULL);
15947 
15948  /* free event data */
15949  if( consdata->eventdata != NULL )
15950  {
15951  /* drop bound change events of variables */
15952  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15953  }
15954  assert(consdata->eventdata == NULL);
15955  }
15956 
15957  /* remove row from NLP, if still in solving
15958  * if we are in exitsolve, the whole NLP will be freed anyway
15959  */
15960  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15961  {
15962  SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15963  }
15964 
15965  return SCIP_OKAY;
15966 }
15967 
15968 
15969 /** frees specific constraint data */
15970 static
15971 SCIP_DECL_CONSDELETE(consDeleteLinear)
15972 { /*lint --e{715}*/
15973  assert(scip != NULL);
15974  assert(conshdlr != NULL);
15975  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15976 
15977  if( (*consdata)->eventdata != NULL )
15978  {
15979  SCIP_CONSHDLRDATA* conshdlrdata;
15980 
15981  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15982  assert(conshdlrdata != NULL);
15983 
15984  /* drop all events */
15985  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15986  assert((*consdata)->eventdata == NULL);
15987  }
15988 
15989  /* free linear constraint */
15990  SCIP_CALL( consdataFree(scip, consdata) );
15991 
15992  return SCIP_OKAY;
15993 }
15994 
15995 
15996 /** transforms constraint data into data belonging to the transformed problem */
15997 static
15998 SCIP_DECL_CONSTRANS(consTransLinear)
15999 { /*lint --e{715}*/
16000  SCIP_CONSDATA* sourcedata;
16001  SCIP_CONSDATA* targetdata;
16002 
16003  /*debugMsg(scip, "Trans method of linear constraints\n");*/
16004 
16005  assert(scip != NULL);
16006  assert(conshdlr != NULL);
16007  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16008  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
16009  assert(sourcecons != NULL);
16010  assert(targetcons != NULL);
16011 
16012  sourcedata = SCIPconsGetData(sourcecons);
16013  assert(sourcedata != NULL);
16014  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
16015 
16016  /* create linear constraint data for target constraint */
16017  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
16018 
16019 #ifndef NDEBUG
16020  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
16021  if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
16022  {
16023  int n;
16024  for(n = targetdata->nvars - 1; n >= 0; --n )
16025  assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
16026  }
16027 #endif
16028 
16029  /* create target constraint */
16030  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
16031  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
16032  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
16033  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
16034  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
16035 
16036  return SCIP_OKAY;
16037 }
16038 
16039 
16040 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
16041 static
16042 SCIP_DECL_CONSINITLP(consInitlpLinear)
16043 { /*lint --e{715}*/
16044  int c;
16045 
16046  assert(scip != NULL);
16047  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16048 
16049  *infeasible = FALSE;
16050 
16051  for( c = 0; c < nconss && !(*infeasible); ++c )
16052  {
16053  assert(SCIPconsIsInitial(conss[c]));
16054  SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
16055  }
16056 
16057  return SCIP_OKAY;
16058 }
16059 
16060 
16061 /** separation method of constraint handler for LP solutions */
16062 static
16063 SCIP_DECL_CONSSEPALP(consSepalpLinear)
16064 { /*lint --e{715}*/
16065  SCIP_CONSHDLRDATA* conshdlrdata;
16066  SCIP_Real loclowerbound;
16067  SCIP_Real glblowerbound;
16068  SCIP_Real cutoffbound;
16069  SCIP_Real maxbound;
16070  SCIP_Bool separatecards;
16071  SCIP_Bool cutoff;
16072  int c;
16073  int depth;
16074  int nrounds;
16075  int maxsepacuts;
16076  int ncuts;
16077 
16078  assert(scip != NULL);
16079  assert(conshdlr != NULL);
16080  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16081  assert(result != NULL);
16083  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16084  assert(conshdlrdata != NULL);
16085  depth = SCIPgetDepth(scip);
16086  nrounds = SCIPgetNSepaRounds(scip);
16087 
16088  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16089 
16090  *result = SCIP_DIDNOTRUN;
16091 
16092  /* only call the separator a given number of times at each node */
16093  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16094  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16095  return SCIP_OKAY;
16096 
16097  /* get the maximal number of cuts allowed in a separation round */
16098  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16099 
16100  /* check if we want to produce knapsack cardinality cuts at this node */
16101  loclowerbound = SCIPgetLocalLowerbound(scip);
16102  glblowerbound = SCIPgetLowerbound(scip);
16103  cutoffbound = SCIPgetCutoffbound(scip);
16104  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16105  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
16106  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
16107 
16108  *result = SCIP_DIDNOTFIND;
16109  ncuts = 0;
16110  cutoff = FALSE;
16111 
16112  /* check all useful linear constraints for feasibility */
16113  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16114  {
16115  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16116  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16117  }
16118 
16119  /* adjust return value */
16120  if( cutoff )
16121  *result = SCIP_CUTOFF;
16122  else if( ncuts > 0 )
16123  *result = SCIP_SEPARATED;
16124 
16125  /* combine linear constraints to get more cuts */
16126  /**@todo further cuts of linear constraints */
16127 
16128  return SCIP_OKAY;
16129 }
16130 
16131 
16132 /** separation method of constraint handler for arbitrary primal solutions */
16133 static
16134 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16135 { /*lint --e{715}*/
16136  SCIP_CONSHDLRDATA* conshdlrdata;
16137  int c;
16138  int depth;
16139  int nrounds;
16140  int maxsepacuts;
16141  int ncuts;
16142  SCIP_Bool cutoff;
16143 
16144  assert(scip != NULL);
16145  assert(conshdlr != NULL);
16146  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16147  assert(result != NULL);
16148 
16149  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16150  assert(conshdlrdata != NULL);
16151  depth = SCIPgetDepth(scip);
16152  nrounds = SCIPgetNSepaRounds(scip);
16154  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16155 
16156  *result = SCIP_DIDNOTRUN;
16157 
16158  /* only call the separator a given number of times at each node */
16159  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16160  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16161  return SCIP_OKAY;
16162 
16163  /* get the maximal number of cuts allowed in a separation round */
16164  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16165 
16166  *result = SCIP_DIDNOTFIND;
16167  ncuts = 0;
16168  cutoff = FALSE;
16169 
16170  /* check all useful linear constraints for feasibility */
16171  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16172  {
16173  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16174  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16175  }
16176 
16177  /* adjust return value */
16178  if( cutoff )
16179  *result = SCIP_CUTOFF;
16180  else if( ncuts > 0 )
16181  *result = SCIP_SEPARATED;
16182 
16183  /* combine linear constraints to get more cuts */
16184  /**@todo further cuts of linear constraints */
16185 
16186  return SCIP_OKAY;
16187 }
16188 
16189 
16190 /** constraint enforcing method of constraint handler for LP solutions */
16191 static
16192 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16193 { /*lint --e{715}*/
16194  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16195 
16196  return SCIP_OKAY;
16197 }
16198 
16199 /** constraint enforcing method of constraint handler for relaxation solutions */
16200 static
16201 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16202 { /*lint --e{715}*/
16203  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16204 
16205  return SCIP_OKAY;
16206 }
16207 
16208 /** constraint enforcing method of constraint handler for pseudo solutions */
16209 static
16210 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16211 { /*lint --e{715}*/
16212  SCIP_CONSHDLRDATA* conshdlrdata;
16213  SCIP_Bool checkrelmaxabs;
16214  SCIP_Bool violated;
16215  int c;
16216 
16217  assert(scip != NULL);
16218  assert(conshdlr != NULL);
16219  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16220  assert(result != NULL);
16221 
16222  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16223  assert(conshdlrdata != NULL);
16224 
16225  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16226 
16227  SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16228 
16229  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16230  if( objinfeasible )
16231  {
16232  SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16233 
16234  *result = SCIP_DIDNOTRUN;
16235  return SCIP_OKAY;
16236  }
16237 
16238  /* check all linear constraints for feasibility */
16239  violated = FALSE;
16240  for( c = 0; c < nconss && !violated; ++c )
16241  {
16242  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16243  }
16244 
16245  if( violated )
16246  *result = SCIP_INFEASIBLE;
16247  else
16248  *result = SCIP_FEASIBLE;
16249 
16250  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16251 
16252  return SCIP_OKAY;
16253 }
16254 
16255 
16256 /** feasibility check method of constraint handler for integral solutions */
16257 static
16258 SCIP_DECL_CONSCHECK(consCheckLinear)
16259 { /*lint --e{715}*/
16260  SCIP_CONSHDLRDATA* conshdlrdata;
16261  SCIP_Bool checkrelmaxabs;
16262  int c;
16263 
16264  assert(scip != NULL);
16265  assert(conshdlr != NULL);
16266  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16267  assert(result != NULL);
16268 
16269  *result = SCIP_FEASIBLE;
16270 
16271  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16272  assert(conshdlrdata != NULL);
16273 
16274  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16275 
16276  /*debugMsg(scip, "Check method of linear constraints\n");*/
16278  /* check all linear constraints for feasibility */
16279  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16280  {
16281  SCIP_Bool violated = FALSE;
16282  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16283 
16284  if( violated )
16285  {
16286  *result = SCIP_INFEASIBLE;
16287 
16288  if( printreason )
16289  {
16290  SCIP_CONSDATA* consdata;
16291  SCIP_Real activity;
16292 
16293  consdata = SCIPconsGetData(conss[c]);
16294  assert( consdata != NULL);
16295 
16296  activity = consdataGetActivity(scip, consdata, sol);
16297 
16298  SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16299  SCIPinfoMessage(scip, NULL, ";\n");
16300 
16301  if( activity == SCIP_INVALID ) /*lint !e777*/
16302  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16303  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16304  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16305  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16306  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16307  }
16308  }
16309  }
16310 
16311  return SCIP_OKAY;
16312 }
16313 
16314 
16315 /** domain propagation method of constraint handler */
16316 static
16317 SCIP_DECL_CONSPROP(consPropLinear)
16318 { /*lint --e{715}*/
16319  SCIP_CONSHDLRDATA* conshdlrdata;
16320  SCIP_Bool rangedrowpropagation = FALSE;
16321  SCIP_Bool tightenbounds;
16322  SCIP_Bool cutoff;
16323 
16324  int nchgbds;
16325  int i;
16326 
16327  assert(scip != NULL);
16328  assert(conshdlr != NULL);
16329  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16330  assert(result != NULL);
16331 
16332  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16333  assert(conshdlrdata != NULL);
16334 
16335  /*debugMsg(scip, "Prop method of linear constraints\n");*/
16337  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16338  if( SCIPinProbing(scip) )
16339  tightenbounds = TRUE;
16340  else
16341  {
16342  int depth;
16343  int propfreq;
16344  int tightenboundsfreq;
16345  int rangedrowfreq;
16346 
16347  depth = SCIPgetDepth(scip);
16348  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16349  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16350  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16351  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16352 
16353  /* check if we want to do ranged row propagation */
16354  rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16355  rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16356  rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16357  rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16358  rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16359  && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16360  }
16361 
16362  cutoff = FALSE;
16363  nchgbds = 0;
16364 
16365  /* process constraints marked for propagation */
16366  for( i = 0; i < nmarkedconss && !cutoff; i++ )
16367  {
16368  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
16369  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16370  conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16371  }
16372 
16373  /* adjust result code */
16374  if( cutoff )
16375  *result = SCIP_CUTOFF;
16376  else if( nchgbds > 0 )
16377  *result = SCIP_REDUCEDDOM;
16378  else
16379  *result = SCIP_DIDNOTFIND;
16380 
16381  return SCIP_OKAY;
16382 }
16383 
16384 
16385 #define MAXCONSPRESOLROUNDS 10
16386 /** presolving method of constraint handler */
16387 static
16388 SCIP_DECL_CONSPRESOL(consPresolLinear)
16389 { /*lint --e{715}*/
16390  SCIP_CONSHDLRDATA* conshdlrdata;
16391  SCIP_CONS* cons;
16392  SCIP_CONSDATA* consdata;
16393  SCIP_Real minactivity;
16394  SCIP_Real maxactivity;
16395  SCIP_Bool isminacttight;
16396  SCIP_Bool ismaxacttight;
16397  SCIP_Bool isminsettoinfinity;
16398  SCIP_Bool ismaxsettoinfinity;
16399  SCIP_Bool cutoff;
16400  int oldnfixedvars;
16401  int oldnaggrvars;
16402  int oldnchgbds;
16403  int oldndelconss;
16404  int oldnupgdconss;
16405  int oldnchgcoefs;
16406  int oldnchgsides;
16407  int firstchange;
16408  int firstupgradetry;
16409  int c;
16410 
16411  assert(scip != NULL);
16412  assert(conshdlr != NULL);
16413  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16414  assert(result != NULL);
16415 
16416  /*debugMsg(scip, "Presol method of linear constraints\n");*/
16417 
16418  /* remember old preprocessing counters */
16419  cutoff = FALSE;
16420  oldnfixedvars = *nfixedvars;
16421  oldnaggrvars = *naggrvars;
16422  oldnchgbds = *nchgbds;
16423  oldndelconss = *ndelconss;
16424  oldnupgdconss = *nupgdconss;
16425  oldnchgcoefs = *nchgcoefs;
16426  oldnchgsides = *nchgsides;
16427 
16428  /* get constraint handler data */
16429  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16430  assert(conshdlrdata != NULL);
16431 
16432  /* process single constraints */
16433  firstchange = INT_MAX;
16434  firstupgradetry = INT_MAX;
16435  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16436  {
16437  int npresolrounds;
16438  SCIP_Bool infeasible;
16439 
16440  infeasible = FALSE;
16441 
16442  cons = conss[c];
16443  assert(SCIPconsIsActive(cons));
16444  consdata = SCIPconsGetData(cons);
16445  assert(consdata != NULL);
16446 
16447  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16448  if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16449  {
16450  consdata->lhs = consdata->rhs;
16451  assert(consdata->row == NULL);
16452  }
16453 
16454  if( consdata->eventdata == NULL )
16455  {
16456  /* catch bound change events of variables */
16457  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16458  assert(consdata->eventdata != NULL);
16459  }
16460 
16461  /* constraint should not be already presolved in the initial round */
16462  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16463  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16464  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16465  assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16466 
16467  /* incorporate fixings and aggregations in constraint */
16468  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16469 
16470  if( infeasible )
16471  {
16472  SCIPdebugMsg(scip, " -> infeasible fixing\n");
16473  cutoff = TRUE;
16474  break;
16475  }
16476 
16477  assert(consdata->removedfixings);
16478 
16479  /* we can only presolve linear constraints, that are not modifiable */
16480  if( SCIPconsIsModifiable(cons) )
16481  continue;
16482 
16483  /* remember the first changed constraint to begin the next aggregation round with */
16484  if( firstchange == INT_MAX && consdata->changed )
16485  firstchange = c;
16486 
16487  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16488  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16489  firstupgradetry = c;
16490 
16491  /* check, if constraint is already preprocessed */
16492  if( consdata->presolved )
16493  continue;
16494 
16495  assert(SCIPconsIsActive(cons));
16496 
16497  SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16498  SCIPdebugPrintCons(scip, cons, NULL);
16499 
16500  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16501  * to avoid nearly infinite cycling due to very small bound changes)
16502  */
16503  npresolrounds = 0;
16504  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16505  {
16506  assert(!cutoff);
16507  npresolrounds++;
16508 
16509  /* mark constraint being presolved and propagated */
16510  consdata->presolved = TRUE;
16511  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
16512 
16513  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16514 
16515  if( infeasible )
16516  {
16517  SCIPdebugMsg(scip, " -> infeasible normalization\n");
16518  cutoff = TRUE;
16519  break;
16520  }
16521 
16522  /* tighten left and right hand side due to integrality */
16523  SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16524 
16525  if( infeasible )
16526  {
16527  SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16528  cutoff = TRUE;
16529  break;
16530  }
16531 
16532  /* check bounds */
16533  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16534  {
16535  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16536  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16537  cutoff = TRUE;
16538  break;
16539  }
16540 
16541  /* tighten variable's bounds */
16542  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16543  if( cutoff )
16544  break;
16545 
16546  /* check for fixed variables */
16547  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16548  if( cutoff )
16549  break;
16550 
16551  /* check constraint for infeasibility and redundancy */
16552  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
16553  &isminsettoinfinity, &ismaxsettoinfinity);
16554  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16555  {
16556  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16557  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16558  cutoff = TRUE;
16559  break;
16560  }
16561  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16562  {
16563  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16564  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16565  SCIP_CALL( SCIPdelCons(scip, cons) );
16566  assert(!SCIPconsIsActive(cons));
16567 
16568  if( !consdata->upgraded )
16569  (*ndelconss)++;
16570  break;
16571  }
16572  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16573  {
16574  SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16575  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16576  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16577  if( !consdata->upgraded )
16578  (*nchgsides)++;
16579  }
16580  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16581  {
16582  SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16583  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16584  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
16585  if( !consdata->upgraded )
16586  (*nchgsides)++;
16587  }
16588 
16589  /* handle empty constraint */
16590  if( consdata->nvars == 0 )
16591  {
16592  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16593  {
16594  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16595  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16596  cutoff = TRUE;
16597  }
16598  else
16599  {
16600  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16601  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16602  SCIP_CALL( SCIPdelCons(scip, cons) );
16603  assert(!SCIPconsIsActive(cons));
16604 
16605  if( !consdata->upgraded )
16606  (*ndelconss)++;
16607  }
16608  break;
16609  }
16610 
16611  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16612  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16613 
16614  /* try to simplify inequalities */
16615  if( conshdlrdata->simplifyinequalities )
16616  {
16617  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16618 
16619  if( cutoff )
16620  break;
16621  }
16622 
16623  /* aggregation variable in equations */
16624  if( conshdlrdata->aggregatevariables )
16625  {
16626  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16627  if( cutoff )
16628  break;
16629  }
16630  }
16631 
16632  if( !cutoff && !SCIPisStopped(scip) )
16633  {
16634  /* perform ranged row propagation */
16635  if( conshdlrdata->rangedrowpropagation )
16636  {
16637  int lastnfixedvars;
16638 
16639  lastnfixedvars = *nfixedvars;
16640 
16641  SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16642  if( !cutoff )
16643  {
16644  if( lastnfixedvars < *nfixedvars )
16645  {
16646  SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16647  }
16648  }
16649  }
16650 
16651  /* extract cliques from constraint */
16652  if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16653  {
16654  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16655  nfixedvars, nchgbds, &cutoff) );
16656 
16657  /* check if the constraint got redundant or infeasible */
16658  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16659  {
16660  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16661  {
16662  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16663  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16664  cutoff = TRUE;
16665  }
16666  else
16667  {
16668  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16669  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16670  SCIP_CALL( SCIPdelCons(scip, cons) );
16671  assert(!SCIPconsIsActive(cons));
16672 
16673  if( !consdata->upgraded )
16674  (*ndelconss)++;
16675  }
16676  }
16677  }
16678 
16679  /* convert special equalities */
16680  if( !cutoff && SCIPconsIsActive(cons) )
16681  {
16682  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16683  }
16684 
16685  /* apply dual presolving for variables that appear in only one constraint */
16686  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16687  {
16688  SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16689  }
16690 
16691  /* check if an inequality is parallel to the objective function */
16692  if( !cutoff && SCIPconsIsActive(cons) )
16693  {
16694  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16695  }
16696 
16697  /* remember the first changed constraint to begin the next aggregation round with */
16698  if( firstchange == INT_MAX && consdata->changed )
16699  firstchange = c;
16700 
16701  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16702  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16703  firstupgradetry = c;
16704  }
16705 
16706  /* singleton column stuffing */
16707  if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16708  (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16709  {
16710  SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16711  conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16712 
16713  /* handle empty constraint */
16714  if( consdata->nvars == 0 )
16715  {
16716  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16717  {
16718  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16719  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16720  cutoff = TRUE;
16721  }
16722  else
16723  {
16724  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16725  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16726  SCIP_CALL( SCIPdelCons(scip, cons) );
16727  assert(!SCIPconsIsActive(cons));
16728 
16729  if( !consdata->upgraded )
16730  (*ndelconss)++;
16731  }
16732  break;
16733  }
16734  }
16735  }
16736 
16737  /* process pairs of constraints: check them for redundancy and try to aggregate them;
16738  * only apply this expensive procedure in exhaustive presolving timing
16739  */
16740  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16741  {
16742  assert(firstchange >= 0);
16743 
16744  if( firstchange < nconss && conshdlrdata->presolusehashing )
16745  {
16746  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16747  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16748  ndelconss, nchgsides) );
16749  }
16750 
16751  if( firstchange < nconss && conshdlrdata->presolpairwise )
16752  {
16753  SCIP_CONS** usefulconss;
16754  int nusefulconss;
16755  int firstchangenew;
16756  SCIP_Longint npaircomparisons;
16757 
16758  npaircomparisons = 0;
16759  oldndelconss = *ndelconss;
16760  oldnchgsides = *nchgsides;
16761  oldnchgcoefs = *nchgcoefs;
16762 
16763  /* allocate temporary memory */
16764  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16765 
16766  nusefulconss = 0;
16767  firstchangenew = -1;
16768  for( c = 0; c < nconss; ++c )
16769  {
16770  /* update firstchange */
16771  if( c == firstchange )
16772  firstchangenew = nusefulconss;
16773 
16774  /* ignore inactive and modifiable constraints */
16775  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16776  continue;
16777 
16778  usefulconss[nusefulconss] = conss[c];
16779  ++nusefulconss;
16780  }
16781  firstchange = firstchangenew;
16782  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16783 
16784  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16785  {
16786  /* constraint has become inactive or modifiable during pairwise presolving */
16787  if( usefulconss[c] == NULL )
16788  continue;
16789 
16790  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16791 
16792  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16793  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16794  &cutoff, ndelconss, nchgsides, nchgcoefs) );
16795 
16796  if( npaircomparisons > conshdlrdata->nmincomparisons )
16797  {
16798  assert(npaircomparisons > 0);
16799  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16800  break;
16801  oldndelconss = *ndelconss;
16802  oldnchgsides = *nchgsides;
16803  oldnchgcoefs = *nchgcoefs;
16804  npaircomparisons = 0;
16805  }
16806  }
16807  /* free temporary memory */
16808  SCIPfreeBufferArray(scip, &usefulconss);
16809  }
16810  }
16811 
16812  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16813  * in linear constraints and we therefore have full information about it
16814  */
16815  if( !cutoff && firstupgradetry < nconss
16816  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16817  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16818  )
16819  {
16820  if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16821  {
16822  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16823  }
16824  }
16825 
16826  /* try to upgrade constraints into a more specific constraint type;
16827  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16828  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16829  */
16830  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16831  {
16832  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16833  {
16834  cons = conss[c];
16835 
16836  /* don't upgrade modifiable constraints */
16837  if( SCIPconsIsModifiable(cons) )
16838  continue;
16839 
16840  consdata = SCIPconsGetData(cons);
16841  assert(consdata != NULL);
16842 
16843  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16844  if( consdata->upgradetried )
16845  continue;
16846  /* @todo force that upgrade will be performed later? */
16847  if( !consdata->presolved )
16848  continue;
16849 
16850  consdata->upgradetried = TRUE;
16851  if( SCIPconsIsActive(cons) )
16852  {
16853  SCIP_CONS* upgdcons;
16854 
16855  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16856  if( upgdcons != NULL )
16857  {
16858  /* add the upgraded constraint to the problem */
16859  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16860  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16861  (*nupgdconss)++;
16862 
16863  /* mark the linear constraint being upgraded and to be removed after presolving;
16864  * don't delete it directly, because it may help to preprocess other linear constraints
16865  */
16866  assert(!consdata->upgraded);
16867  consdata->upgraded = TRUE;
16868 
16869  /* delete upgraded inequalities immediately;
16870  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16871  */
16872  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16873  || !conshdlrdata->presolpairwise
16874  || (conshdlrdata->maxaggrnormscale == 0.0) )
16875  {
16876  SCIP_CALL( SCIPdelCons(scip, cons) );
16877  }
16878  }
16879  }
16880  }
16881  }
16882 
16883  /* return the correct result code */
16884  if( cutoff )
16885  *result = SCIP_CUTOFF;
16886  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16887  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16888  *result = SCIP_SUCCESS;
16889  else
16890  *result = SCIP_DIDNOTFIND;
16891 
16892  return SCIP_OKAY;
16893 }
16894 
16895 
16896 /** propagation conflict resolving method of constraint handler */
16897 static
16898 SCIP_DECL_CONSRESPROP(consRespropLinear)
16899 { /*lint --e{715}*/
16900  assert(scip != NULL);
16901  assert(cons != NULL);
16902  assert(result != NULL);
16903 
16904  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16905 
16906  return SCIP_OKAY;
16907 }
16908 
16909 
16910 /** variable rounding lock method of constraint handler */
16911 static
16912 SCIP_DECL_CONSLOCK(consLockLinear)
16913 { /*lint --e{715}*/
16914  SCIP_CONSDATA* consdata;
16915  SCIP_Bool haslhs;
16916  SCIP_Bool hasrhs;
16917  int i;
16918 
16919  assert(scip != NULL);
16920  assert(cons != NULL);
16921  consdata = SCIPconsGetData(cons);
16922  assert(consdata != NULL);
16923 
16924  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16925  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16926 
16927  /* update rounding locks of every single variable */
16928  for( i = 0; i < consdata->nvars; ++i )
16929  {
16930  if( SCIPisPositive(scip, consdata->vals[i]) )
16931  {
16932  if( haslhs )
16933  {
16934  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16935  }
16936  if( hasrhs )
16937  {
16938  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16939  }
16940  }
16941  else
16942  {
16943  if( haslhs )
16944  {
16945  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16946  }
16947  if( hasrhs )
16948  {
16949  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16950  }
16951  }
16952  }
16953 
16954  return SCIP_OKAY;
16955 }
16956 
16957 
16958 /** variable deletion method of constraint handler */
16959 static
16960 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16961 {
16962  assert(scip != NULL);
16963  assert(conshdlr != NULL);
16964  assert(conss != NULL || nconss == 0);
16965 
16966  if( nconss > 0 )
16967  {
16968  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16969  }
16970 
16971  return SCIP_OKAY;
16972 }
16973 
16974 /** constraint display method of constraint handler */
16975 static
16976 SCIP_DECL_CONSPRINT(consPrintLinear)
16977 { /*lint --e{715}*/
16978  assert(scip != NULL);
16979  assert(conshdlr != NULL);
16980  assert(cons != NULL);
16981 
16982  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16983 
16984  return SCIP_OKAY;
16985 }
16986 
16987 /** constraint copying method of constraint handler */
16988 static
16989 SCIP_DECL_CONSCOPY(consCopyLinear)
16990 { /*lint --e{715}*/
16991  SCIP_VAR** sourcevars;
16992  SCIP_Real* sourcecoefs;
16993  const char* consname;
16994  int nvars;
16996  assert(scip != NULL);
16997  assert(sourcescip != NULL);
16998  assert(sourcecons != NULL);
16999 
17000  /* get variables and coefficients of the source constraint */
17001  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
17002  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
17003  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
17004 
17005  if( name != NULL )
17006  consname = name;
17007  else
17008  consname = SCIPconsGetName(sourcecons);
17009 
17010  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
17011  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
17012  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
17013  assert(cons != NULL || *valid == FALSE);
17014 
17015  /* @todo should also the checkabsolute flag of the constraint be copied? */
17016 
17017  return SCIP_OKAY;
17018 }
17019 
17020 /** find operators '<=', '==', '>=', [free] in input string and return those places
17021  *
17022  * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
17023  */
17024 static
17025 void findOperators(
17026  const char* str, /**< null terminated input string */
17027  char** firstoperator, /**< pointer to store the string starting at the first operator */
17028  char** secondoperator, /**< pointer to store the string starting at the second operator */
17029  SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
17030  )
17031 {
17032  char* curr;
17033 
17034  assert(str != NULL);
17035  assert(firstoperator != NULL);
17036  assert(secondoperator != NULL);
17037 
17038  *firstoperator = NULL;
17039  *secondoperator = NULL;
17040 
17041  curr = (char*)str;
17042  *success = TRUE;
17043 
17044  /* loop over the input string to find all operators */
17045  while( *curr && *success )
17046  {
17047  SCIP_Bool found = FALSE;
17048  int increment = 1;
17049 
17050  /* try if we found a possible operator */
17051  switch( *curr )
17052  {
17053  case '<':
17054  case '=':
17055  case '>':
17056 
17057  /* check if the two characters curr[0,1] form an operator together */
17058  if( curr[1] == '=' )
17059  {
17060  found = TRUE;
17061 
17062  /* update increment to continue after this operator */
17063  increment = 2;
17064  }
17065  break;
17066  case '[':
17067  if( strncmp(curr, "[free]", 6) == 0 )
17068  {
17069  found = TRUE;
17070 
17071  /* update increment to continue after this operator */
17072  increment = 6;
17073  }
17074  break;
17075  default:
17076  break;
17077  }
17078 
17079  /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
17080  if( found )
17081  {
17082  if( *firstoperator == NULL )
17083  {
17084  *firstoperator = curr;
17085  }
17086  else
17087  {
17088  if( *secondoperator != NULL )
17089  {
17090  SCIPerrorMessage("Found more than two operators in line %s\n", str);
17091  *success = FALSE;
17092  }
17093  else if( strncmp(*firstoperator, "<=", 2) != 0 )
17094  {
17095  SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17096  *success = FALSE;
17097  }
17098  else if( strncmp(curr, "<=", 2) != 0 )
17099  {
17100  SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17101  *success = FALSE;
17102  }
17103 
17104  *secondoperator = curr;
17105  }
17106  }
17107 
17108  curr += increment;
17109  }
17110 
17111  /* check if we did find at least one operator */
17112  if( *success )
17113  {
17114  if( *firstoperator == NULL )
17115  {
17116  SCIPerrorMessage("Could not find any operator in line %s\n", str);
17117  *success = FALSE;
17118  }
17119  }
17120 }
17121 
17122 /** constraint parsing method of constraint handler */
17123 static
17124 SCIP_DECL_CONSPARSE(consParseLinear)
17125 { /*lint --e{715}*/
17126  SCIP_VAR** vars;
17127  SCIP_Real* coefs;
17128  int nvars;
17129  int coefssize;
17130  int requsize;
17131  SCIP_Real lhs;
17132  SCIP_Real rhs;
17133  char* endptr;
17134  char* firstop;
17135  char* secondop;
17136  SCIP_Bool operatorsuccess;
17137  char* lhsstrptr;
17138  char* rhsstrptr;
17139  char* varstrptr;
17140 
17141  assert(scip != NULL);
17142  assert(success != NULL);
17143  assert(str != NULL);
17144  assert(name != NULL);
17145  assert(cons != NULL);
17146 
17147  /* set left and right hand side to their default values */
17148  lhs = -SCIPinfinity(scip);
17149  rhs = SCIPinfinity(scip);
17150 
17151  (*success) = FALSE;
17152 
17153  /* return of string empty */
17154  if( !*str )
17155  return SCIP_OKAY;
17156 
17157  /* ignore whitespace */
17158  SCIP_CALL( SCIPskipSpace((char**)&str) );
17159 
17160  /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17161  * and the special word [free]
17162  */
17163  findOperators(str, &firstop, &secondop, &operatorsuccess);
17164 
17165  /* if the grammar is not valid for parsing a linear constraint, return */
17166  if( ! operatorsuccess )
17167  return SCIP_OKAY;
17168 
17169  varstrptr = (char *)str;
17170  lhsstrptr = rhsstrptr = NULL;
17171  assert(firstop != NULL);
17172 
17173  /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17174  switch( *firstop )
17175  {
17176  case '<':
17177  assert(firstop[1] == '=');
17178  /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17179  if( secondop != NULL )
17180  {
17181  assert(secondop[0] == '<' && secondop[1] == '=');
17182  lhsstrptr = (char *)str;
17183  varstrptr = firstop + 2;
17184  rhsstrptr = secondop + 2;
17185  }
17186  else
17187  {
17188  /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17189  lhsstrptr = NULL;
17190  varstrptr = (char *)str;
17191  rhsstrptr = firstop + 2;
17192  }
17193  break;
17194  case '>':
17195  assert(firstop[1] == '=');
17196  assert(secondop == NULL);
17197  /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17198  lhsstrptr = firstop + 2;
17199  break;
17200  case '=':
17201  assert(firstop[1] == '=');
17202  assert(secondop == NULL);
17203  /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17204  rhsstrptr = firstop + 2;
17205  lhsstrptr = firstop + 2;
17206  break;
17207  case '[':
17208  assert(strncmp(firstop, "[free]", 6) == 0);
17209  assert(secondop == NULL);
17210  /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17211  break;
17212  default:
17213  /* it should not be possible that a different character appears in that position */
17214  SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17215  return SCIP_READERROR;
17216  }
17217 
17218  /* parse left hand side, if necessary */
17219  if( lhsstrptr != NULL )
17220  {
17221  if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17222  {
17223  SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17224  return SCIP_OKAY;
17225  }
17226 
17227  /* in case of an equation, assign the left also to the right hand side */
17228  if( rhsstrptr == lhsstrptr )
17229  rhs = lhs;
17230  }
17231 
17232  /* parse right hand side, if different from left hand side */
17233  if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17234  {
17235  if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17236  {
17237  SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17238  return SCIP_OKAY;
17239  }
17240  }
17241 
17242  /* initialize buffers for storing the variables and coefficients */
17243  coefssize = 100;
17244  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17245  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17246 
17247  assert(varstrptr != NULL);
17248 
17249  /* parse linear sum to get variables and coefficients */
17250  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17251 
17252  if( *success && requsize > coefssize )
17253  {
17254  /* realloc buffers and try again */
17255  coefssize = requsize;
17256  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17257  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17258 
17259  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17260  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17261  }
17262 
17263  if( !*success )
17264  {
17265  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17266  }
17267  else
17268  {
17269  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17270  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17271  }
17272 
17273  SCIPfreeBufferArray(scip, &coefs);
17274  SCIPfreeBufferArray(scip, &vars);
17275 
17276  return SCIP_OKAY;
17277 }
17278 
17279 
17280 /** constraint method of constraint handler which returns the variables (if possible) */
17281 static
17282 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17283 { /*lint --e{715}*/
17284  SCIP_CONSDATA* consdata;
17285 
17286  consdata = SCIPconsGetData(cons);
17287  assert(consdata != NULL);
17288 
17289  if( varssize < consdata->nvars )
17290  (*success) = FALSE;
17291  else
17292  {
17293  assert(vars != NULL);
17294 
17295  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17296  (*success) = TRUE;
17297  }
17298 
17299  return SCIP_OKAY;
17300 }
17302 /**! [Callback for the number of variables]*/
17303 /** constraint method of constraint handler which returns the number of variables (if possible) */
17304 static
17305 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17306 { /*lint --e{715}*/
17307  SCIP_CONSDATA* consdata;
17308 
17309  consdata = SCIPconsGetData(cons);
17310  assert(consdata != NULL);
17311 
17312  (*nvars) = consdata->nvars;
17313  (*success) = TRUE;
17314 
17315  return SCIP_OKAY;
17316 }
17317 /**! [Callback for the number of variables]*/
17318 
17319 /** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17320 static
17321 SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17322 { /*lint --e{715}*/
17323  SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17325  return SCIP_OKAY;
17326 }
17327 
17328 /** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17329 static
17330 SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17331 { /*lint --e{715}*/
17332  SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17333 
17334  return SCIP_OKAY;
17335 }
17336 
17337 /*
17338  * Callback methods of event handler
17339  */
17341 /** execution method of event handler */
17342 static
17343 SCIP_DECL_EVENTEXEC(eventExecLinear)
17344 { /*lint --e{715}*/
17345  SCIP_CONS* cons;
17346  SCIP_CONSDATA* consdata;
17347  SCIP_VAR* var;
17348  SCIP_EVENTTYPE eventtype;
17350  assert(scip != NULL);
17351  assert(eventhdlr != NULL);
17352  assert(eventdata != NULL);
17353  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17354  assert(event != NULL);
17355 
17356  cons = eventdata->cons;
17357  assert(cons != NULL);
17358  consdata = SCIPconsGetData(cons);
17359  assert(consdata != NULL);
17360 
17361  /* we can skip events droped for deleted constraints */
17362  if( SCIPconsIsDeleted(cons) )
17363  return SCIP_OKAY;
17364 
17365  eventtype = SCIPeventGetType(event);
17366  var = SCIPeventGetVar(event);
17367 
17368  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17369  {
17370  SCIP_Real oldbound;
17371  SCIP_Real newbound;
17372  SCIP_Real val;
17373  int varpos;
17374 
17375  varpos = eventdata->varpos;
17376  assert(0 <= varpos && varpos < consdata->nvars);
17377  oldbound = SCIPeventGetOldbound(event);
17378  newbound = SCIPeventGetNewbound(event);
17379  assert(var != NULL);
17380  assert(consdata->vars[varpos] == var);
17381  val = consdata->vals[varpos];
17382 
17383  /* we only need to update the activities if the constraint is active,
17384  * otherwise we mark them to be invalid
17385  */
17386  if( SCIPconsIsActive(cons) )
17387  {
17388  /* update the activity values */
17389  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17390  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17391  else
17392  {
17393  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17394  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17395  }
17396  }
17397  else
17398  consdataInvalidateActivities(consdata);
17399 
17400  consdata->presolved = FALSE;
17401  consdata->rangedrowpropagated = 0;
17402 
17403  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17404  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17405  {
17406  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
17407 
17408  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17409  if( consdata->maxactdeltavar == var )
17410  {
17411  consdata->maxactdelta = SCIP_INVALID;
17412  consdata->maxactdeltavar = NULL;
17413  }
17414 
17415  /* check whether bound tightening might now be successful */
17416  if( consdata->boundstightened > 0)
17417  {
17418  switch( eventtype )
17419  {
17421  if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17422  consdata->boundstightened = 0;
17423  break;
17425  if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17426  consdata->boundstightened = 0;
17427  break;
17428  default:
17429  SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17430  return SCIP_INVALIDDATA;
17431  }
17432  }
17433  }
17434  /* update maximal activity delta if a bound was relaxed */
17435  else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17436  {
17437  SCIP_Real lb;
17438  SCIP_Real ub;
17439  SCIP_Real domain;
17440  SCIP_Real delta;
17441 
17442  assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17443 
17444  lb = SCIPvarGetLbLocal(var);
17445  ub = SCIPvarGetUbLocal(var);
17446 
17447  domain = ub - lb;
17448  delta = REALABS(val) * domain;
17449 
17450  if( delta > consdata->maxactdelta )
17451  {
17452  consdata->maxactdelta = delta;
17453  consdata->maxactdeltavar = var;
17454  }
17455  }
17456  }
17457  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17458  {
17459  /* we want to remove the fixed variable */
17460  consdata->presolved = FALSE;
17461  consdata->removedfixings = FALSE;
17462  consdata->rangedrowpropagated = 0;
17463 
17464  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17465  if( consdata->maxactdeltavar == var )
17466  {
17467  consdata->maxactdelta = SCIP_INVALID;
17468  consdata->maxactdeltavar = NULL;
17469  }
17470  }
17471  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17472  {
17473  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17474  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17475  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17476  consdata->presolved = FALSE;
17477  }
17478  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17479  {
17480  SCIP_Real oldbound;
17481  SCIP_Real newbound;
17482  SCIP_Real val;
17483  int varpos;
17484 
17485  varpos = eventdata->varpos;
17486  assert(0 <= varpos && varpos < consdata->nvars);
17487  oldbound = SCIPeventGetOldbound(event);
17488  newbound = SCIPeventGetNewbound(event);
17489  assert(var != NULL);
17490  assert(consdata->vars[varpos] == var);
17491  val = consdata->vals[varpos];
17492 
17493  consdata->rangedrowpropagated = 0;
17494 
17495  /* update the activity values */
17496  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17497  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17498  else
17499  {
17500  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17501  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17502  }
17503 
17504  /* if the variable is binary but not fixed it had to become binary due to this global change */
17505  if( SCIPvarIsBinary(var) && SCIPisGT(scip, SCIPvarGetUbGlobal(var), SCIPvarGetLbGlobal(var)) )
17506  {
17507  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
17508  consdata->indexsorted = FALSE;
17509  else
17510  consdata->coefsorted = FALSE;
17511  }
17512  }
17513  else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17514  {
17515  assert(SCIPgetStage(scip) < SCIP_STAGE_PRESOLVED);
17516 
17517  /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17518  consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17519 
17520  /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17521  consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17522  }
17523  else
17524  {
17525  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17526  consdata->varsdeleted = TRUE;
17527  }
17528 
17529  return SCIP_OKAY;
17530 }
17531 
17532 
17533 /*
17534  * Callback methods of conflict handler
17535  */
17536 
17537 /** conflict processing method of conflict handler (called when conflict was found) */
17538 static
17539 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17540 { /*lint --e{715}*/
17541  SCIP_VAR** vars;
17542  SCIP_Real* vals;
17543  SCIP_Real lhs;
17544  int i;
17545 
17546  assert(scip != NULL);
17547  assert(conflicthdlr != NULL);
17548  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17549  assert(bdchginfos != NULL || nbdchginfos == 0);
17550  assert(result != NULL);
17551 
17552  /* don't process already resolved conflicts */
17553  if( resolved )
17554  {
17555  *result = SCIP_DIDNOTRUN;
17556  return SCIP_OKAY;
17557  }
17559  *result = SCIP_DIDNOTFIND;
17560 
17561  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17562  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17563  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17564  lhs = 1.0;
17565  for( i = 0; i < nbdchginfos; ++i )
17566  {
17567  assert(bdchginfos != NULL);
17568 
17569  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17570 
17571  /* we can only treat binary variables */
17572  /**@todo extend linear conflict constraints to some non-binary cases */
17573  if( !SCIPvarIsBinary(vars[i]) )
17574  break;
17575 
17576  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17577  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17578  vals[i] = 1.0;
17579  else
17580  {
17581  vals[i] = -1.0;
17582  lhs -= 1.0;
17583  }
17584  }
17585 
17586  if( i == nbdchginfos )
17587  {
17588  SCIP_CONS* cons;
17589  SCIP_CONS* upgdcons;
17590  char consname[SCIP_MAXSTRLEN];
17591 
17592  /* create a constraint out of the conflict set */
17593  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
17594  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17595  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17596 
17597  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17598  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17599  if( upgdcons != NULL )
17600  {
17601  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17602  cons = upgdcons;
17603  }
17604 
17605  /* add conflict to SCIP */
17606  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17607 
17608  *result = SCIP_CONSADDED;
17609  }
17610 
17611  /* free temporary memory */
17612  SCIPfreeBufferArray(scip, &vals);
17613  SCIPfreeBufferArray(scip, &vars);
17614 
17615  return SCIP_OKAY;
17616 }
17617 
17618 
17619 /*
17620  * Nonlinear constraint upgrading
17621  */
17622 
17623 /** tries to upgrade a nonlinear constraint into a linear constraint */
17624 static
17625 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17626 {
17627  SCIP_CONSDATA* consdata;
17628  SCIP_EXPR* expr;
17629  SCIP_Real lhs;
17630  SCIP_Real rhs;
17631  int i;
17632 
17633  assert(nupgdconss != NULL);
17634  assert(upgdconss != NULL);
17635  assert(upgdconsssize > 0);
17636 
17637  expr = SCIPgetExprNonlinear(cons);
17638  assert(expr != NULL);
17639 
17640  /* not a linear constraint if the expression is not a sum
17641  * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17642  */
17643  if( !SCIPisExprSum(scip, expr) )
17644  return SCIP_OKAY;
17645 
17646  /* if at least one child is not a variable, then not a linear constraint */
17647  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17648  if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17649  return SCIP_OKAY;
17650 
17651  /* consider constant part of the sum expression */
17652  lhs = SCIPisInfinity(scip, -SCIPgetLhsNonlinear(cons)) ? -SCIPinfinity(scip) : (SCIPgetLhsNonlinear(cons) - SCIPgetConstantExprSum(expr));
17653  rhs = SCIPisInfinity(scip, SCIPgetRhsNonlinear(cons)) ? SCIPinfinity(scip) : (SCIPgetRhsNonlinear(cons) - SCIPgetConstantExprSum(expr));
17654 
17655  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17656  0, NULL, NULL, lhs, rhs,
17660  SCIPconsIsStickingAtNode(cons)) );
17661  assert(upgdconss[0] != NULL);
17662 
17663  consdata = SCIPconsGetData(upgdconss[0]);
17664 
17665  /* add linear terms */
17666  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, SCIPexprGetNChildren(expr)) );
17667  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17668  {
17669  SCIP_CALL( addCoef(scip, upgdconss[0], SCIPgetVarExprVar(SCIPexprGetChildren(expr)[i]), SCIPgetCoefsExprSum(expr)[i]) );
17670  }
17671 
17672  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17673  consdata->checkabsolute = TRUE;
17674 
17675  *nupgdconss = 1;
17676 
17677  SCIPdebugMsg(scip, "created linear constraint:\n");
17678  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17679 
17680  return SCIP_OKAY;
17681 } /*lint !e715*/
17682 
17683 /*
17684  * constraint specific interface methods
17685  */
17686 
17687 /** creates the handler for linear constraints and includes it in SCIP */
17689  SCIP* scip /**< SCIP data structure */
17690  )
17691 {
17692  SCIP_CONSHDLRDATA* conshdlrdata;
17693  SCIP_CONSHDLR* conshdlr;
17694  SCIP_EVENTHDLR* eventhdlr;
17695  SCIP_CONFLICTHDLR* conflicthdlr;
17696 
17697  assert(scip != NULL);
17698 
17699  /* create event handler for bound change events */
17701  eventExecLinear, NULL) );
17702 
17703  /* create conflict handler for linear constraints */
17705  conflictExecLinear, NULL) );
17706 
17707  /* create constraint handler data */
17708  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17709 
17710  /* include constraint handler */
17713  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17714  conshdlrdata) );
17715 
17716  assert(conshdlr != NULL);
17717 
17718  /* set non-fundamental callbacks via specific setter functions */
17719  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17720  SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17721  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17722  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17723  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17724  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17725  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17726  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17727  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17728  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17729  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17730  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17731  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17732  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17733  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17734  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
17735  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17736  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
17738  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17739  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17741  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17742  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17743  SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17744  SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17745 
17746  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17747  {
17748  /* include the linear constraint upgrade in the nonlinear constraint handler */
17750  }
17751 
17752  /* add linear constraint handler parameters */
17753  SCIP_CALL( SCIPaddIntParam(scip,
17754  "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17755  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17756  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17757  SCIP_CALL( SCIPaddIntParam(scip,
17758  "constraints/" CONSHDLR_NAME "/maxrounds",
17759  "maximal number of separation rounds per node (-1: unlimited)",
17760  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17761  SCIP_CALL( SCIPaddIntParam(scip,
17762  "constraints/" CONSHDLR_NAME "/maxroundsroot",
17763  "maximal number of separation rounds per node in the root node (-1: unlimited)",
17764  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17765  SCIP_CALL( SCIPaddIntParam(scip,
17766  "constraints/" CONSHDLR_NAME "/maxsepacuts",
17767  "maximal number of cuts separated per separation round",
17768  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17769  SCIP_CALL( SCIPaddIntParam(scip,
17770  "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17771  "maximal number of cuts separated per separation round in the root node",
17772  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17774  "constraints/" CONSHDLR_NAME "/presolpairwise",
17775  "should pairwise constraint comparison be performed in presolving?",
17776  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17778  "constraints/" CONSHDLR_NAME "/presolusehashing",
17779  "should hash table be used for detecting redundant constraints in advance",
17780  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17781  SCIP_CALL( SCIPaddIntParam(scip,
17782  "constraints/" CONSHDLR_NAME "/nmincomparisons",
17783  "number for minimal pairwise presolve comparisons",
17784  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17786  "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17787  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17788  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17790  "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17791  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17792  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17794  "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17795  "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17796  &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17798  "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17799  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17800  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17802  "constraints/" CONSHDLR_NAME "/separateall",
17803  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17804  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17806  "constraints/" CONSHDLR_NAME "/aggregatevariables",
17807  "should presolving search for aggregations in equations",
17808  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17810  "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17811  "should presolving try to simplify inequalities",
17812  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17814  "constraints/" CONSHDLR_NAME "/dualpresolving",
17815  "should dual presolving steps be performed?",
17816  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17818  "constraints/" CONSHDLR_NAME "/singletonstuffing",
17819  "should stuffing of singleton continuous variables be performed?",
17820  &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17822  "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17823  "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17824  &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17826  "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17827  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17829  "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17830  "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)?",
17831  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17833  "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17834  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17835  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17837  "constraints/" CONSHDLR_NAME "/detectlowerbound",
17838  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17839  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17841  "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17842  "should presolving try to detect subsets of constraints parallel to the objective function?",
17843  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17845  "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17846  "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17847  &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17849  "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17850  "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17851  &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17852  SCIP_CALL( SCIPaddIntParam(scip,
17853  "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17854  "maximum depth to apply ranged row propagation",
17855  &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17856  SCIP_CALL( SCIPaddIntParam(scip,
17857  "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17858  "frequency for applying ranged row propagation",
17859  &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17861  "constraints/" CONSHDLR_NAME "/multaggrremove",
17862  "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17863  &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17865  "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17866  "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17867  &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17869  "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17870  "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17871  &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17873  "constraints/" CONSHDLR_NAME "/extractcliques",
17874  "should Cliques be extracted?",
17875  &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17876 
17877  return SCIP_OKAY;
17878 }
17879 
17880 /** includes a linear constraint update method into the linear constraint handler */
17882  SCIP* scip, /**< SCIP data structure */
17883  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17884  int priority, /**< priority of upgrading method */
17885  const char* conshdlrname /**< name of the constraint handler */
17886  )
17887 {
17888  SCIP_CONSHDLR* conshdlr;
17889  SCIP_CONSHDLRDATA* conshdlrdata;
17890  SCIP_LINCONSUPGRADE* linconsupgrade;
17891  char paramname[SCIP_MAXSTRLEN];
17892  char paramdesc[SCIP_MAXSTRLEN];
17893 
17894  assert(scip != NULL);
17895  assert(linconsupgd != NULL);
17896  assert(conshdlrname != NULL );
17897 
17898  /* find the linear constraint handler */
17899  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17900  if( conshdlr == NULL )
17901  {
17902  SCIPerrorMessage("linear constraint handler not found\n");
17903  return SCIP_PLUGINNOTFOUND;
17904  }
17905 
17906  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17907  assert(conshdlrdata != NULL);
17908 
17909  /* check if linear constraint update method already exists in constraint handler data */
17910  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17911  {
17912  /* create a linear constraint upgrade data object */
17913  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17914 
17915  /* insert linear constraint update method into constraint handler data */
17916  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17917 
17918  /* adds parameter to turn on and off the upgrading step */
17919  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17920  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17922  paramname, paramdesc,
17923  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17924  }
17925 
17926  return SCIP_OKAY;
17927 }
17928 
17929 /** creates and captures a linear constraint
17930  *
17931  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17932  */
17934  SCIP* scip, /**< SCIP data structure */
17935  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17936  const char* name, /**< name of constraint */
17937  int nvars, /**< number of nonzeros in the constraint */
17938  SCIP_VAR** vars, /**< array with variables of constraint entries */
17939  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17940  SCIP_Real lhs, /**< left hand side of constraint */
17941  SCIP_Real rhs, /**< right hand side of constraint */
17942  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17943  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17944  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17945  * Usually set to TRUE. */
17946  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17947  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17948  SCIP_Bool check, /**< should the constraint be checked for feasibility?
17949  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17950  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17951  * Usually set to TRUE. */
17952  SCIP_Bool local, /**< is constraint only valid locally?
17953  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17954  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17955  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17956  * adds coefficients to this constraint. */
17957  SCIP_Bool dynamic, /**< is constraint subject to aging?
17958  * Usually set to FALSE. Set to TRUE for own cuts which
17959  * are separated as constraints. */
17960  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17961  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17962  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17963  * if it may be moved to a more global node?
17964  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17965  )
17966 {
17967  SCIP_CONSHDLR* conshdlr;
17968  SCIP_CONSDATA* consdata;
17969  int j;
17970 
17971  assert(scip != NULL);
17972  assert(cons != NULL);
17973 
17974  /* find the linear constraint handler */
17975  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17976  if( conshdlr == NULL )
17977  {
17978  SCIPerrorMessage("linear constraint handler not found\n");
17979  return SCIP_PLUGINNOTFOUND;
17980  }
17981 
17982  for( j = 0; j < nvars; ++j )
17983  {
17984  if( SCIPisInfinity(scip, REALABS(vals[j])) )
17985  {
17986  SCIPerrorMessage("coefficient of variable <%s> is infinite.\n", SCIPvarGetName(vars[j]));
17987  SCIPABORT();
17988  return SCIP_INVALIDDATA;
17989  }
17990  }
17991 
17992  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17993  * constraint after presolving we have to ensure that it holds active variables
17994  */
17995  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17996  {
17997  SCIP_VAR** consvars;
17998  SCIP_Real* consvals;
17999  SCIP_Real constant = 0.0;
18000  int nconsvars;
18001  int requiredsize;
18002 
18003  nconsvars = nvars;
18004  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
18005  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
18006 
18007  /* get active variables for new constraint */
18008  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18009 
18010  /* if space was not enough we need to resize the buffers */
18011  if( requiredsize > nconsvars )
18012  {
18013  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18014  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18015 
18016  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18017  assert(requiredsize <= nconsvars);
18018  }
18019 
18020  /* adjust sides and check that we do not subtract infinity values */
18021  if( SCIPisInfinity(scip, REALABS(constant)) )
18022  {
18023  if( constant < 0.0 )
18024  {
18025  if( SCIPisInfinity(scip, lhs) )
18026  {
18027  SCIPfreeBufferArray(scip, &consvals);
18028  SCIPfreeBufferArray(scip, &consvars);
18029 
18030  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);
18031 
18032  SCIPABORT();
18033  return SCIP_INVALIDDATA; /*lint !e527*/
18034  }
18035  if( SCIPisInfinity(scip, rhs) )
18036  {
18037  SCIPfreeBufferArray(scip, &consvals);
18038  SCIPfreeBufferArray(scip, &consvars);
18039 
18040  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);
18041 
18042  SCIPABORT();
18043  return SCIP_INVALIDDATA; /*lint !e527*/
18044  }
18045 
18046  lhs = -SCIPinfinity(scip);
18047  rhs = -SCIPinfinity(scip);
18048  }
18049  else
18050  {
18051  if( SCIPisInfinity(scip, -lhs) )
18052  {
18053  SCIPfreeBufferArray(scip, &consvals);
18054  SCIPfreeBufferArray(scip, &consvars);
18055 
18056  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);
18057 
18058  SCIPABORT();
18059  return SCIP_INVALIDDATA; /*lint !e527*/
18060  }
18061  if( SCIPisInfinity(scip, -rhs) )
18062  {
18063  SCIPfreeBufferArray(scip, &consvals);
18064  SCIPfreeBufferArray(scip, &consvars);
18065 
18066  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);
18067 
18068  SCIPABORT();
18069  return SCIP_INVALIDDATA; /*lint !e527*/
18070  }
18071 
18072  lhs = SCIPinfinity(scip);
18073  rhs = SCIPinfinity(scip);
18074  }
18075  }
18076  else
18077  {
18078  if( !SCIPisInfinity(scip, REALABS(lhs)) )
18079  lhs -= constant;
18080  if( !SCIPisInfinity(scip, REALABS(rhs)) )
18081  rhs -= constant;
18082 
18083  if( SCIPisInfinity(scip, -lhs) )
18084  lhs = -SCIPinfinity(scip);
18085  else if( SCIPisInfinity(scip, lhs) )
18086  lhs = SCIPinfinity(scip);
18087 
18088  if( SCIPisInfinity(scip, rhs) )
18089  rhs = SCIPinfinity(scip);
18090  else if( SCIPisInfinity(scip, -rhs) )
18091  rhs = -SCIPinfinity(scip);
18092  }
18093 
18094  /* create constraint data */
18095  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
18096  assert(consdata != NULL);
18097 
18098  SCIPfreeBufferArray(scip, &consvals);
18099  SCIPfreeBufferArray(scip, &consvars);
18100  }
18101  else
18102  {
18103  /* create constraint data */
18104  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18105  assert(consdata != NULL);
18106  }
18107 
18108 #ifndef NDEBUG
18109  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18110  if( check || enforce )
18111  {
18112  int n;
18113  for(n = consdata->nvars - 1; n >= 0; --n )
18114  assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18115  }
18116 #endif
18117 
18118  /* create constraint */
18119  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18120  local, modifiable, dynamic, removable, stickingatnode) );
18121 
18122  return SCIP_OKAY;
18123 }
18124 
18125 /** creates and captures a linear constraint
18126  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18127  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18128  *
18129  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18130  *
18131  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18132  */
18134  SCIP* scip, /**< SCIP data structure */
18135  SCIP_CONS** cons, /**< pointer to hold the created constraint */
18136  const char* name, /**< name of constraint */
18137  int nvars, /**< number of nonzeros in the constraint */
18138  SCIP_VAR** vars, /**< array with variables of constraint entries */
18139  SCIP_Real* vals, /**< array with coefficients of constraint entries */
18140  SCIP_Real lhs, /**< left hand side of constraint */
18141  SCIP_Real rhs /**< right hand side of constraint */
18142  )
18143 {
18144  assert(scip != NULL);
18145 
18146  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18147  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
18148 
18149  return SCIP_OKAY;
18150 }
18151 
18152 /** creates by copying and captures a linear constraint */
18154  SCIP* scip, /**< target SCIP data structure */
18155  SCIP_CONS** cons, /**< pointer to store the created target constraint */
18156  SCIP* sourcescip, /**< source SCIP data structure */
18157  const char* name, /**< name of constraint */
18158  int nvars, /**< number of variables in source variable array */
18159  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18160  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18161  SCIP_Real lhs, /**< left hand side of the linear constraint */
18162  SCIP_Real rhs, /**< right hand side of the linear constraint */
18163  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18164  * variables of the target SCIP */
18165  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18166  * target constraints */
18167  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18168  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18169  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18170  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18171  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18172  SCIP_Bool local, /**< is constraint only valid locally? */
18173  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18174  SCIP_Bool dynamic, /**< is constraint subject to aging? */
18175  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18176  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18177  * if it may be moved to a more global node? */
18178  SCIP_Bool global, /**< create a global or a local copy? */
18179  SCIP_Bool* valid /**< pointer to store if the copying was valid */
18180  )
18181 {
18182  SCIP_VAR** vars;
18183  SCIP_Real* coefs;
18184 
18185  SCIP_Real constant;
18186  int requiredsize;
18187  int v;
18188  SCIP_Bool success;
18189 
18190  if( SCIPisGT(scip, lhs, rhs) )
18191  {
18192  *valid = FALSE;
18193  return SCIP_OKAY;
18194  }
18195 
18196  (*valid) = TRUE;
18197 
18198  if( nvars == 0 )
18199  {
18200  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18201  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18202  return SCIP_OKAY;
18203  }
18204 
18205  /* duplicate variable array */
18206  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
18207 
18208  /* duplicate coefficient array */
18209  if( sourcecoefs != NULL )
18210  {
18211  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18212  }
18213  else
18214  {
18215  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18216  for( v = 0; v < nvars; ++v )
18217  coefs[v] = 1.0;
18218  }
18219 
18220  constant = 0.0;
18221 
18222  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18223  * the target SCIP
18224  */
18225  if( !SCIPvarIsOriginal(vars[0]) )
18226  {
18227  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18228 
18229  if( requiredsize > nvars )
18230  {
18231  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18232  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18233 
18234  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18235  assert(requiredsize <= nvars);
18236  }
18237  }
18238  else
18239  {
18240  for( v = 0; v < nvars; ++v )
18241  {
18242  assert(SCIPvarIsOriginal(vars[v]));
18243  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18244  assert(vars[v] != NULL);
18245  }
18246  }
18247 
18248  success = TRUE;
18249  /* map variables of the source constraint to variables of the target SCIP */
18250  for( v = 0; v < nvars && success; ++v )
18251  {
18252  SCIP_VAR* var;
18253  var = vars[v];
18254 
18255  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18256  assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18257 
18258  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18259  assert(!(success) || vars[v] != NULL);
18260  }
18261 
18262  /* only create the target constraint, if all variables could be copied */
18263  if( success )
18264  {
18265  if( !SCIPisInfinity(scip, -lhs) )
18266  lhs -= constant;
18267 
18268  if( !SCIPisInfinity(scip, rhs) )
18269  rhs -= constant;
18270 
18271  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18272  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18273  }
18274  else
18275  *valid = FALSE;
18276 
18277  /* free buffer array */
18278  SCIPfreeBufferArray(scip, &coefs);
18279  SCIPfreeBufferArray(scip, &vars);
18280 
18281  return SCIP_OKAY;
18282 }
18283 
18284 /** adds coefficient to linear constraint (if it is not zero) */
18286  SCIP* scip, /**< SCIP data structure */
18287  SCIP_CONS* cons, /**< constraint data */
18288  SCIP_VAR* var, /**< variable of constraint entry */
18289  SCIP_Real val /**< coefficient of constraint entry */
18290  )
18291 {
18292  assert(scip != NULL);
18293  assert(cons != NULL);
18294  assert(var != NULL);
18295 
18296  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18297  {
18298  SCIPerrorMessage("constraint is not linear\n");
18299  return SCIP_INVALIDDATA;
18300  }
18301 
18302  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18303  * constraint after presolving we have to ensure that it holds active variables
18304  */
18305  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
18306  {
18307  SCIP_CONSDATA* consdata;
18308  SCIP_VAR** consvars;
18309  SCIP_Real* consvals;
18310  SCIP_Real constant = 0.0;
18311  SCIP_Real rhs;
18312  SCIP_Real lhs;
18313  int nconsvars;
18314  int requiredsize;
18315  int v;
18316 
18317  nconsvars = 1;
18318  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18319  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18320  consvars[0] = var;
18321  consvals[0] = val;
18322 
18323  /* get active variables for new constraint */
18324  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18325 
18326  /* if space was not enough we need to resize the buffers */
18327  if( requiredsize > nconsvars )
18328  {
18329  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18330  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18331 
18332  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18333  assert(requiredsize <= nconsvars);
18334  }
18335 
18336  consdata = SCIPconsGetData(cons);
18337  assert(consdata != NULL);
18338 
18339  lhs = consdata->lhs;
18340  rhs = consdata->rhs;
18341 
18342  /* adjust sides and check that we do not subtract infinity values */
18343  /* constant is infinite */
18344  if( SCIPisInfinity(scip, REALABS(constant)) )
18345  {
18346  if( constant < 0.0 )
18347  {
18348  if( SCIPisInfinity(scip, lhs) )
18349  {
18350  SCIPfreeBufferArray(scip, &consvals);
18351  SCIPfreeBufferArray(scip, &consvars);
18352 
18353  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));
18354 
18355  SCIPABORT();
18356  return SCIP_INVALIDDATA; /*lint !e527*/
18357  }
18358  if( SCIPisInfinity(scip, rhs) )
18359  {
18360  SCIPfreeBufferArray(scip, &consvals);
18361  SCIPfreeBufferArray(scip, &consvars);
18362 
18363  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));
18364 
18365  SCIPABORT();
18366  return SCIP_INVALIDDATA; /*lint !e527*/
18367  }
18368 
18369  lhs = -SCIPinfinity(scip);
18370  rhs = -SCIPinfinity(scip);
18371  }
18372  else
18373  {
18374  if( SCIPisInfinity(scip, -lhs) )
18375  {
18376  SCIPfreeBufferArray(scip, &consvals);
18377  SCIPfreeBufferArray(scip, &consvars);
18378 
18379  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));
18380 
18381  SCIPABORT();
18382  return SCIP_INVALIDDATA; /*lint !e527*/
18383  }
18384  if( SCIPisInfinity(scip, -rhs) )
18385  {
18386  SCIPfreeBufferArray(scip, &consvals);
18387  SCIPfreeBufferArray(scip, &consvars);
18388 
18389  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));
18390 
18391  SCIPABORT();
18392  return SCIP_INVALIDDATA; /*lint !e527*/
18393  }
18394 
18395  lhs = SCIPinfinity(scip);
18396  rhs = SCIPinfinity(scip);
18397  }
18398  }
18399  /* constant is not infinite */
18400  else
18401  {
18402  if( !SCIPisInfinity(scip, REALABS(lhs)) )
18403  lhs -= constant;
18404  if( !SCIPisInfinity(scip, REALABS(rhs)) )
18405  rhs -= constant;
18406 
18407  if( SCIPisInfinity(scip, -lhs) )
18408  lhs = -SCIPinfinity(scip);
18409  else if( SCIPisInfinity(scip, lhs) )
18410  lhs = SCIPinfinity(scip);
18411 
18412  if( SCIPisInfinity(scip, rhs) )
18413  rhs = SCIPinfinity(scip);
18414  else if( SCIPisInfinity(scip, -rhs) )
18415  rhs = -SCIPinfinity(scip);
18416  }
18417 
18418  /* add all active variables to constraint */
18419  for( v = nconsvars - 1; v >= 0; --v )
18420  {
18421  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18422  }
18423 
18424  /* update left and right hand sides */
18425  SCIP_CALL( chgLhs(scip, cons, lhs));
18426  SCIP_CALL( chgRhs(scip, cons, rhs));
18427 
18428  SCIPfreeBufferArray(scip, &consvals);
18429  SCIPfreeBufferArray(scip, &consvars);
18430  }
18431  else
18432  {
18433  SCIP_CALL( addCoef(scip, cons, var, val) );
18434  }
18435 
18436  return SCIP_OKAY;
18437 }
18438 
18439 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18440  * not yet contained in the constraint
18441  *
18442  * @note This method may only be called during problem creation stage for an original constraint and variable.
18443  *
18444  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18445  */
18447  SCIP* scip, /**< SCIP data structure */
18448  SCIP_CONS* cons, /**< constraint data */
18449  SCIP_VAR* var, /**< variable of constraint entry */
18450  SCIP_Real val /**< new coefficient of constraint entry */
18451  )
18452 {
18453  SCIP_CONSDATA* consdata;
18454  SCIP_VAR** vars;
18455  SCIP_Bool found;
18456  int i;
18457 
18458  assert(scip != NULL);
18459  assert(cons != NULL);
18460  assert(var != NULL);
18461 
18462  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18463  {
18464  SCIPerrorMessage("constraint is not linear\n");
18466  }
18467 
18468  if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
18469  {
18470  SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18471  return SCIP_INVALIDDATA;
18472  }
18473 
18474  consdata = SCIPconsGetData(cons);
18475  assert(consdata != NULL);
18476 
18477  vars = consdata->vars;
18478  found = FALSE;
18479  i = 0;
18480  while( i < consdata->nvars )
18481  {
18482  if( vars[i] == var )
18483  {
18484  if( found || SCIPisZero(scip, val) )
18485  {
18486  SCIP_CALL( delCoefPos(scip, cons, i) );
18487 
18488  /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18489  i--;
18490  }
18491  else
18492  {
18493  SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18494  }
18495  found = TRUE;
18496  }
18497  i++;
18498  }
18499 
18500  if( !found && !SCIPisZero(scip, val) )
18501  {
18502  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18503  }
18504 
18505  return SCIP_OKAY;
18506 }
18507 
18508 /** deletes variable from linear constraint
18509  *
18510  * @note This method may only be called during problem creation stage for an original constraint and variable.
18511  *
18512  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18513  */
18515  SCIP* scip, /**< SCIP data structure */
18516  SCIP_CONS* cons, /**< constraint data */
18517  SCIP_VAR* var /**< variable of constraint entry */
18518  )
18519 {
18520  assert(scip != NULL);
18521  assert(cons != NULL);
18522  assert(var != NULL);
18523 
18524  SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18525 
18526  return SCIP_OKAY;
18527 }
18528 
18529 /** gets left hand side of linear constraint */
18531  SCIP* scip, /**< SCIP data structure */
18532  SCIP_CONS* cons /**< constraint data */
18533  )
18534 {
18535  SCIP_CONSDATA* consdata;
18536 
18537  assert(scip != NULL);
18538  assert(cons != NULL);
18539 
18540  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18541  {
18542  SCIPerrorMessage("constraint is not linear\n");
18543  SCIPABORT();
18544  return SCIP_INVALID; /*lint !e527*/
18545  }
18546 
18547  consdata = SCIPconsGetData(cons);
18548  assert(consdata != NULL);
18550  return consdata->lhs;
18551 }
18552 
18553 /** gets right hand side of linear constraint */
18555  SCIP* scip, /**< SCIP data structure */
18556  SCIP_CONS* cons /**< constraint data */
18557  )
18558 {
18559  SCIP_CONSDATA* consdata;
18560 
18561  assert(scip != NULL);
18562  assert(cons != NULL);
18563 
18564  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18565  {
18566  SCIPerrorMessage("constraint is not linear\n");
18567  SCIPABORT();
18568  return SCIP_INVALID; /*lint !e527*/
18569  }
18570 
18571  consdata = SCIPconsGetData(cons);
18572  assert(consdata != NULL);
18574  return consdata->rhs;
18575 }
18576 
18577 /** changes left hand side of linear constraint */
18579  SCIP* scip, /**< SCIP data structure */
18580  SCIP_CONS* cons, /**< constraint data */
18581  SCIP_Real lhs /**< new left hand side */
18582  )
18583 {
18584  assert(scip != NULL);
18585  assert(cons != NULL);
18586 
18587  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18588  {
18589  SCIPerrorMessage("constraint is not linear\n");
18590  return SCIP_INVALIDDATA;
18591  }
18592 
18593  SCIP_CALL( chgLhs(scip, cons, lhs) );
18594 
18595  return SCIP_OKAY;
18596 }
18598 /** changes right hand side of linear constraint */
18600  SCIP* scip, /**< SCIP data structure */
18601  SCIP_CONS* cons, /**< constraint data */
18602  SCIP_Real rhs /**< new right hand side */
18603  )
18604 {
18605  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18606  {
18607  SCIPerrorMessage("constraint is not linear\n");
18608  return SCIP_INVALIDDATA;
18609  }
18610 
18611  SCIP_CALL( chgRhs(scip, cons, rhs) );
18612 
18613  return SCIP_OKAY;
18614 }
18615 
18616 /** gets the number of variables in the linear constraint */
18617 int SCIPgetNVarsLinear(
18618  SCIP* scip, /**< SCIP data structure */
18619  SCIP_CONS* cons /**< constraint data */
18620  )
18621 {
18622  SCIP_CONSDATA* consdata;
18623 
18624  assert(scip != NULL);
18625  assert(cons != NULL);
18626 
18627  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18628  {
18629  SCIPerrorMessage("constraint is not linear\n");
18630  SCIPABORT();
18631  return -1; /*lint !e527*/
18632  }
18633 
18634  consdata = SCIPconsGetData(cons);
18635  assert(consdata != NULL);
18637  return consdata->nvars;
18638 }
18639 
18640 /** gets the array of variables in the linear constraint; the user must not modify this array! */
18642  SCIP* scip, /**< SCIP data structure */
18643  SCIP_CONS* cons /**< constraint data */
18644  )
18645 {
18646  SCIP_CONSDATA* consdata;
18647 
18648  assert(scip != NULL);
18649  assert(cons != NULL);
18650 
18651  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18652  {
18653  SCIPerrorMessage("constraint is not linear\n");
18654  SCIPABORT();
18655  return NULL; /*lint !e527*/
18656  }
18657 
18658  consdata = SCIPconsGetData(cons);
18659  assert(consdata != NULL);
18661  return consdata->vars;
18662 }
18663 
18664 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18666  SCIP* scip, /**< SCIP data structure */
18667  SCIP_CONS* cons /**< constraint data */
18668  )
18669 {
18670  SCIP_CONSDATA* consdata;
18671 
18672  assert(scip != NULL);
18673  assert(cons != NULL);
18674 
18675  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18676  {
18677  SCIPerrorMessage("constraint is not linear\n");
18678  SCIPABORT();
18679  return NULL; /*lint !e527*/
18680  }
18681 
18682  consdata = SCIPconsGetData(cons);
18683  assert(consdata != NULL);
18685  return consdata->vals;
18686 }
18687 
18688 /** gets the activity of the linear constraint in the given solution
18689  *
18690  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18691  * comprises positive and negative infinity contributions
18692  */
18694  SCIP* scip, /**< SCIP data structure */
18695  SCIP_CONS* cons, /**< constraint data */
18696  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18697  )
18698 {
18699  SCIP_CONSDATA* consdata;
18700 
18701  assert(scip != NULL);
18702  assert(cons != NULL);
18703 
18704  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18705  {
18706  SCIPerrorMessage("constraint is not linear\n");
18707  SCIPABORT();
18708  return SCIP_INVALID; /*lint !e527*/
18709  }
18710 
18711  consdata = SCIPconsGetData(cons);
18712  assert(consdata != NULL);
18713 
18714  if( consdata->row != NULL )
18715  return SCIPgetRowSolActivity(scip, consdata->row, sol);
18716  else
18717  return consdataGetActivity(scip, consdata, sol);
18718 }
18719 
18720 /** gets the feasibility of the linear constraint in the given solution */
18722  SCIP* scip, /**< SCIP data structure */
18723  SCIP_CONS* cons, /**< constraint data */
18724  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18725  )
18726 {
18727  SCIP_CONSDATA* consdata;
18728 
18729  assert(scip != NULL);
18730  assert(cons != NULL);
18731 
18732  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18733  {
18734  SCIPerrorMessage("constraint is not linear\n");
18735  SCIPABORT();
18736  return SCIP_INVALID; /*lint !e527*/
18737  }
18738 
18739  consdata = SCIPconsGetData(cons);
18740  assert(consdata != NULL);
18741 
18742  if( consdata->row != NULL )
18743  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18744  else
18745  return consdataGetFeasibility(scip, consdata, sol);
18746 }
18747 
18748 /** gets the dual solution of the linear constraint in the current LP */
18750  SCIP* scip, /**< SCIP data structure */
18751  SCIP_CONS* cons /**< constraint data */
18752  )
18753 {
18754  SCIP_CONSDATA* consdata;
18755 
18756  assert(scip != NULL);
18757  assert(cons != NULL);
18758  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18759 
18760  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18761  {
18762  SCIPerrorMessage("constraint is not linear\n");
18763  SCIPABORT();
18764  return SCIP_INVALID; /*lint !e527*/
18765  }
18766 
18767  consdata = SCIPconsGetData(cons);
18768  assert(consdata != NULL);
18769 
18770  if( consdata->row != NULL )
18771  return SCIProwGetDualsol(consdata->row);
18772  else
18773  return 0.0;
18774 }
18775 
18776 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18778  SCIP* scip, /**< SCIP data structure */
18779  SCIP_CONS* cons /**< constraint data */
18780  )
18781 {
18782  SCIP_CONSDATA* consdata;
18783 
18784  assert(scip != NULL);
18785  assert(cons != NULL);
18786  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18787 
18788  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18789  {
18790  SCIPerrorMessage("constraint is not linear\n");
18791  SCIPABORT();
18792  return SCIP_INVALID; /*lint !e527*/
18793  }
18794 
18795  consdata = SCIPconsGetData(cons);
18796  assert(consdata != NULL);
18797 
18798  if( consdata->row != NULL )
18799  return SCIProwGetDualfarkas(consdata->row);
18800  else
18801  return 0.0;
18802 }
18803 
18804 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18805  * the user must not modify the row!
18806  */
18808  SCIP* scip, /**< SCIP data structure */
18809  SCIP_CONS* cons /**< constraint data */
18810  )
18811 {
18812  SCIP_CONSDATA* consdata;
18813 
18814  assert(scip != NULL);
18815  assert(cons != NULL);
18816 
18817  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18818  {
18819  SCIPerrorMessage("constraint is not linear\n");
18820  SCIPABORT();
18821  return NULL; /*lint !e527*/
18822  }
18823 
18824  consdata = SCIPconsGetData(cons);
18825  assert(consdata != NULL);
18827  return consdata->row;
18828 }
18829 
18830 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18832  SCIP* scip, /**< SCIP data structure */
18833  SCIP_CONS* cons, /**< source constraint to try to convert */
18834  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18835  )
18836 {
18837  SCIP_CONSHDLR* conshdlr;
18838  SCIP_CONSHDLRDATA* conshdlrdata;
18839  SCIP_CONSDATA* consdata;
18840  SCIP_VAR* var;
18841  SCIP_Real val;
18842  SCIP_Real lb;
18843  SCIP_Real ub;
18844  SCIP_Real poscoeffsum;
18845  SCIP_Real negcoeffsum;
18846  SCIP_Bool infeasible;
18847  SCIP_Bool integral;
18848  int nchgsides = 0;
18849  int nposbin;
18850  int nnegbin;
18851  int nposint;
18852  int nnegint;
18853  int nposimpl;
18854  int nnegimpl;
18855  int nposimplbin;
18856  int nnegimplbin;
18857  int nposcont;
18858  int nnegcont;
18859  int ncoeffspone;
18860  int ncoeffsnone;
18861  int ncoeffspint;
18862  int ncoeffsnint;
18863  int ncoeffspfrac;
18864  int ncoeffsnfrac;
18865  int i;
18866 
18867  assert(scip != NULL);
18868  assert(cons != NULL);
18869  assert(upgdcons != NULL);
18870 
18871  *upgdcons = NULL;
18872 
18873  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18874  if( SCIPconsIsModifiable(cons) )
18875  return SCIP_OKAY;
18876 
18877  /* check for upgradability */
18878  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18879  return SCIP_OKAY;
18880 
18881  /* get the constraint handler and check, if it's really a linear constraint */
18882  conshdlr = SCIPconsGetHdlr(cons);
18883  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18884  {
18885  SCIPerrorMessage("constraint is not linear\n");
18886  return SCIP_INVALIDDATA;
18887  }
18888 
18889  /* get constraint handler data and constraint data */
18890  conshdlrdata = SCIPconshdlrGetData(conshdlr);
18891  assert(conshdlrdata != NULL);
18892  consdata = SCIPconsGetData(cons);
18893  assert(consdata != NULL);
18894 
18895  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18896  if( consdata->upgraded )
18897  return SCIP_OKAY;
18898 
18899  /* check, if the constraint is already stored as LP row */
18900  if( consdata->row != NULL )
18901  {
18902  if( SCIProwIsInLP(consdata->row) )
18903  {
18904  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18905  return SCIP_INVALIDDATA;
18906  }
18907  else
18908  {
18909  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18910  }
18911  }
18912 
18913  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18914 
18915  /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18916  * skipped and we hope that the infeasibility gets detected later again.
18917  *
18918  * TODO: do we want to try to upgrade the constraint anyway?
18919  *
18920  * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18921  * proven to be infeasible.
18922  */
18923  if( infeasible ) /*lint !e774*/
18924  return SCIP_OKAY;
18925 
18926  /* tighten sides */
18927  SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18928 
18929  if( infeasible ) /*lint !e774*/
18930  return SCIP_OKAY;
18931 
18932  /*
18933  * calculate some statistics on linear constraint
18934  */
18935 
18936  nposbin = 0;
18937  nnegbin = 0;
18938  nposint = 0;
18939  nnegint = 0;
18940  nposimpl = 0;
18941  nnegimpl = 0;
18942  nposimplbin = 0;
18943  nnegimplbin = 0;
18944  nposcont = 0;
18945  nnegcont = 0;
18946  ncoeffspone = 0;
18947  ncoeffsnone = 0;
18948  ncoeffspint = 0;
18949  ncoeffsnint = 0;
18950  ncoeffspfrac = 0;
18951  ncoeffsnfrac = 0;
18952  integral = TRUE;
18953  poscoeffsum = 0.0;
18954  negcoeffsum = 0.0;
18955 
18956  for( i = 0; i < consdata->nvars; ++i )
18957  {
18958  var = consdata->vars[i];
18959  val = consdata->vals[i];
18960  lb = SCIPvarGetLbLocal(var);
18961  ub = SCIPvarGetUbLocal(var);
18962  assert(!SCIPisZero(scip, val));
18963 
18964  switch( SCIPvarGetType(var) )
18965  {
18966  case SCIP_VARTYPE_BINARY:
18967  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18968  integral = integral && SCIPisIntegral(scip, val);
18969  if( val >= 0.0 )
18970  nposbin++;
18971  else
18972  nnegbin++;
18973  break;
18974  case SCIP_VARTYPE_INTEGER:
18975  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18976  integral = integral && SCIPisIntegral(scip, val);
18977  if( val >= 0.0 )
18978  nposint++;
18979  else
18980  nnegint++;
18981  break;
18982  case SCIP_VARTYPE_IMPLINT:
18983  if( SCIPvarIsBinary(var) )
18984  {
18985  if( val >= 0.0 )
18986  nposimplbin++;
18987  else
18988  nnegimplbin++;
18989  }
18990  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18991  integral = integral && SCIPisIntegral(scip, val);
18992  if( val >= 0.0 )
18993  nposimpl++;
18994  else
18995  nnegimpl++;
18996  break;
18998  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18999  if( val >= 0.0 )
19000  nposcont++;
19001  else
19002  nnegcont++;
19003  break;
19004  default:
19005  SCIPerrorMessage("unknown variable type\n");
19006  return SCIP_INVALIDDATA;
19007  }
19008  if( SCIPisEQ(scip, val, 1.0) )
19009  ncoeffspone++;
19010  else if( SCIPisEQ(scip, val, -1.0) )
19011  ncoeffsnone++;
19012  else if( SCIPisIntegral(scip, val) )
19013  {
19014  if( SCIPisPositive(scip, val) )
19015  ncoeffspint++;
19016  else
19017  ncoeffsnint++;
19018  }
19019  else
19020  {
19021  if( SCIPisPositive(scip, val) )
19022  ncoeffspfrac++;
19023  else
19024  ncoeffsnfrac++;
19025  }
19026  if( SCIPisPositive(scip, val) )
19027  poscoeffsum += val;
19028  else
19029  negcoeffsum += val;
19030  }
19031 
19032  /*
19033  * call the upgrading methods
19034  */
19035 
19036  SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
19037  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
19038  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",
19039  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
19040  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
19041  poscoeffsum, negcoeffsum, integral);
19042 
19043  /* try all upgrading methods in priority order in case the upgrading step is enable */
19044  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
19045  {
19046  if( conshdlrdata->linconsupgrades[i]->active )
19047  {
19048  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
19049  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
19050  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
19051  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
19052  poscoeffsum, negcoeffsum, integral,
19053  upgdcons) );
19054  }
19055  }
19056 
19057 #ifdef SCIP_DEBUG
19058  if( *upgdcons != NULL )
19059  {
19060  SCIPdebugPrintCons(scip, cons, NULL);
19061  SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
19062  SCIPdebugPrintCons(scip, *upgdcons, NULL);
19063  }
19064 #endif
19065 
19066  return SCIP_OKAY; /*lint !e438*/
19067 }
19068 
19069 /** cleans up (multi-)aggregations and fixings from linear constraints */
19071  SCIP* scip, /**< SCIP data structure */
19072  SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
19073  SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
19074  )
19075 {
19076  SCIP_CONSHDLR* conshdlr;
19077  SCIP_CONS** conss;
19078  int nconss;
19079  int i;
19080 
19081  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
19082  if( conshdlr == NULL )
19083  return SCIP_OKAY;
19084 
19085  assert(infeasible != NULL);
19086  *infeasible = FALSE;
19087 
19088  nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
19089  conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
19090 
19091  for( i = 0; i < nconss; ++i )
19092  {
19093  SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
19094 
19095  if( *infeasible )
19096  break;
19097  }
19098 
19099  return SCIP_OKAY;
19100 }
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:6839
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 void consdataGetGlbActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *glbminactivity, SCIP_Real *glbmaxactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2886
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
Definition: cons_linear.c:4026
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:3164
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:3185
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:7910
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:9571
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:5449
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:4257
#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 permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3339
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 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
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 *istight, SCIP_Bool *issettoinfinity)
Definition: cons_linear.c:2421
#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:7672
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:5854
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:3230
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
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2609
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:9015
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:5118
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:5327
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:7289
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:5379
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:3610
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:3415
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
#define QUAD(x)
Definition: dbldblarith.h:47
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:9137
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:5183
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:3905
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:5234
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
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:5519
#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)
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:4105
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)
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 *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2946
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:7762
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)
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 *istight, SCIP_Bool *issettoinfinity)
Definition: cons_linear.c:2516
#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:3482
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:4198
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:3096
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:670
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:7107
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:4577
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7573
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:64
#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:7549
#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:2656
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:5351
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:3210
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:5796
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)
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:8045
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:9627
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:7111
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:9685
#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:4648
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:3740
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:7978
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:9739
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 void consdataGetActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2737
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:4936
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:7636
#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