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-2025 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
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"
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? */
109
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
112
113#define EVENTHDLR_NAME "linear"
114#define EVENTHDLR_DESC "bound change event handler for linear constraints"
115
116#define CONFLICTHDLR_NAME "linear"
117#define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
118#define CONFLICTHDLR_PRIORITY -1000000
119
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 */
175
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 */
178
179
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 */
188struct 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 */
270struct 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 */
278struct 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 */
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
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 */
355typedef enum Proprule PROPRULE;
356
357/** inference information */
358struct 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};
370typedef struct InferInfo INFERINFO;
371
372/** converts an integer into an inference information */
373static
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 */
386static
388 INFERINFO inferinfo /**< inference information to convert */
389 )
390{
391 return inferinfo.val.asint;
392}
393
394/** returns the propagation rule stored in the inference information */
395static
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 */
404static
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 */
413static
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));
424
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 */
432static
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 */
447static
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);
467
468 return SCIP_OKAY;
469}
470
471/** ensures, that vars and vals arrays can store at least num entries */
472static
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 */
507static
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 */
528static
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 */
542static
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 */
566static
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}
586
587/** creates a linear constraint upgrade data object */
588static
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 */
618static
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 */
650static
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( val < 0.0 )
669 {
670 SCIP_CALL( SCIPlockVarCons(scip, var, cons,
671 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
672 }
673 else
674 {
675 SCIP_CALL( SCIPlockVarCons(scip, var, cons,
676 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
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 */
683static
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( val < 0.0 )
702 {
703 SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
704 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
705 }
706 else
707 {
708 SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
709 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
710 }
711
712 return SCIP_OKAY;
713}
714
715/** creates event data for variable at given position, and catches events */
716/**! [SnippetDebugAssertions] */
717static
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 */
756static
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 */
790static
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 */
822static
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 */
853static
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 SCIP_VAR** varsbuffer;
902 SCIP_Real* valsbuffer;
903
904 /* copy variables into temporary buffer */
905 SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
906 SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
907 nvars = 0;
908
909 /* loop over variables and sort out fixed ones */
910 for( v = 0; v < (*consdata)->nvars; ++v )
911 {
912 SCIP_VAR* var;
913 SCIP_Real val;
914
915 var = vars[v];
916 val = vals[v];
917
918 assert(var != NULL);
919 if( !SCIPisZero(scip, val) )
920 {
921 /* treat fixed variable as a constant if problem compression is enabled */
923 {
924 constant += SCIPvarGetLbGlobal(var) * val;
925 }
926 else
927 {
928 varsbuffer[nvars] = var;
929 valsbuffer[nvars] = val;
930 ++nvars;
931
932 /* update hascontvar and hasnonbinvar flags */
933 if( !(*consdata)->hascontvar )
934 {
935 SCIP_VARTYPE vartype = SCIPvarGetType(var);
936
937 if( vartype != SCIP_VARTYPE_BINARY )
938 {
939 (*consdata)->hasnonbinvar = TRUE;
940
941 if( vartype == SCIP_VARTYPE_CONTINUOUS )
942 (*consdata)->hascontvar = TRUE;
943 }
944 }
945 }
946 }
947 }
948 (*consdata)->nvars = nvars;
949
950 if( nvars > 0 )
951 {
952 /* copy the possibly reduced buffer arrays into block */
953 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, nvars) );
954 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, nvars) );
955 (*consdata)->varssize = nvars;
956 }
957 /* free temporary buffer */
958 SCIPfreeBufferArray(scip, &valsbuffer);
959 SCIPfreeBufferArray(scip, &varsbuffer);
960 }
961
962 (*consdata)->eventdata = NULL;
963
964 /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
965 if( !SCIPisZero(scip, constant) )
966 {
967 if( !SCIPisInfinity(scip, REALABS(lhs)) )
968 lhs -= constant;
969
970 if( !SCIPisInfinity(scip, REALABS(rhs)) )
971 rhs -= constant;
972 }
973
974 (*consdata)->row = NULL;
975 (*consdata)->nlrow = NULL;
976 (*consdata)->lhs = lhs;
977 (*consdata)->rhs = rhs;
978 (*consdata)->maxabsval = SCIP_INVALID;
979 (*consdata)->minabsval = SCIP_INVALID;
980 QUAD_ASSIGN((*consdata)->minactivity, SCIP_INVALID);
981 QUAD_ASSIGN((*consdata)->maxactivity, SCIP_INVALID);
982 (*consdata)->lastminactivity = SCIP_INVALID;
983 (*consdata)->lastmaxactivity = SCIP_INVALID;
984 (*consdata)->maxactdelta = SCIP_INVALID;
985 (*consdata)->maxactdeltavar = NULL;
986 (*consdata)->minactivityneginf = -1;
987 (*consdata)->minactivityposinf = -1;
988 (*consdata)->maxactivityneginf = -1;
989 (*consdata)->maxactivityposinf = -1;
990 (*consdata)->minactivityneghuge = -1;
991 (*consdata)->minactivityposhuge = -1;
992 (*consdata)->maxactivityneghuge = -1;
993 (*consdata)->maxactivityposhuge = -1;
994 QUAD_ASSIGN((*consdata)->glbminactivity, SCIP_INVALID);
995 QUAD_ASSIGN((*consdata)->glbmaxactivity, SCIP_INVALID);
996 (*consdata)->lastglbminactivity = SCIP_INVALID;
997 (*consdata)->lastglbmaxactivity = SCIP_INVALID;
998 (*consdata)->glbminactivityneginf = -1;
999 (*consdata)->glbminactivityposinf = -1;
1000 (*consdata)->glbmaxactivityneginf = -1;
1001 (*consdata)->glbmaxactivityposinf = -1;
1002 (*consdata)->glbminactivityneghuge = -1;
1003 (*consdata)->glbminactivityposhuge = -1;
1004 (*consdata)->glbmaxactivityneghuge = -1;
1005 (*consdata)->glbmaxactivityposhuge = -1;
1006 (*consdata)->possignature = 0;
1007 (*consdata)->negsignature = 0;
1008 (*consdata)->validmaxabsval = FALSE;
1009 (*consdata)->validminabsval = FALSE;
1010 (*consdata)->validactivities = FALSE;
1011 (*consdata)->validminact = FALSE;
1012 (*consdata)->validmaxact = FALSE;
1013 (*consdata)->validglbminact = FALSE;
1014 (*consdata)->validglbmaxact = FALSE;
1015 (*consdata)->boundstightened = 0;
1016 (*consdata)->presolved = FALSE;
1017 (*consdata)->removedfixings = FALSE;
1018 (*consdata)->validsignature = FALSE;
1019 (*consdata)->changed = TRUE;
1020 (*consdata)->normalized = FALSE;
1021 (*consdata)->upgradetried = FALSE;
1022 (*consdata)->upgraded = FALSE;
1023 (*consdata)->indexsorted = (nvars <= 1);
1024 (*consdata)->merged = (nvars <= 1);
1025 (*consdata)->cliquesadded = FALSE;
1026 (*consdata)->implsadded = FALSE;
1027 (*consdata)->coefsorted = FALSE;
1028 (*consdata)->nbinvars = -1;
1029 (*consdata)->varsdeleted = FALSE;
1030 (*consdata)->rangedrowpropagated = 0;
1031 (*consdata)->checkabsolute = FALSE;
1032
1033 if( SCIPisTransformed(scip) )
1034 {
1035 /* get transformed variables */
1036 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1037 }
1038
1039 /* capture variables */
1040 for( v = 0; v < (*consdata)->nvars; v++ )
1041 {
1042 /* likely implies a deleted variable */
1043 if( (*consdata)->vars[v] == NULL )
1044 {
1045 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1046 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1047 SCIPfreeBlockMemory(scip, consdata);
1048 return SCIP_INVALIDDATA;
1049 }
1050
1051 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1052 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1053 }
1054
1055 return SCIP_OKAY;
1056}
1057
1058/** frees a linear constraint data */
1059static
1061 SCIP* scip, /**< SCIP data structure */
1062 SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1063 )
1064{
1065 int v;
1066
1067 assert(scip != NULL);
1068 assert(consdata != NULL);
1069 assert(*consdata != NULL);
1070 assert((*consdata)->varssize >= 0);
1071
1072 /* release the row */
1073 if( (*consdata)->row != NULL )
1074 {
1075 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1076 }
1077
1078 /* release the nlrow */
1079 if( (*consdata)->nlrow != NULL )
1080 {
1081 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
1082 }
1083
1084 /* release variables */
1085 for( v = 0; v < (*consdata)->nvars; v++ )
1086 {
1087 assert((*consdata)->vars[v] != NULL);
1088 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1089 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1090 }
1091
1092 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1093 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1094 SCIPfreeBlockMemory(scip, consdata);
1095
1096 return SCIP_OKAY;
1097}
1098
1099/** prints linear constraint in CIP format to file stream */
1100static
1102 SCIP* scip, /**< SCIP data structure */
1103 SCIP_CONSDATA* consdata, /**< linear constraint data */
1104 FILE* file /**< output file (or NULL for standard output) */
1105 )
1106{
1107 assert(scip != NULL);
1108 assert(consdata != NULL);
1109
1110 /* print left hand side for ranged rows */
1111 if( !SCIPisInfinity(scip, -consdata->lhs)
1112 && !SCIPisInfinity(scip, consdata->rhs)
1113 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1114 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1115
1116 /* print coefficients and variables */
1117 if( consdata->nvars == 0 )
1118 SCIPinfoMessage(scip, file, "0");
1119 else
1120 {
1121 /* post linear sum of the linear constraint */
1122 SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1123 }
1124
1125 /* print right hand side */
1126 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1127 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1128 else if( !SCIPisInfinity(scip, consdata->rhs) )
1129 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1130 else if( !SCIPisInfinity(scip, -consdata->lhs) )
1131 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1132 else
1133 SCIPinfoMessage(scip, file, " [free]");
1134
1135 return SCIP_OKAY;
1136}
1137
1138/** prints linear constraint and contained solution values of variables to file stream */
1139static
1141 SCIP* scip, /**< SCIP data structure */
1142 SCIP_CONS* cons, /**< linear constraint */
1143 SCIP_SOL* sol, /**< solution to print */
1144 FILE* file /**< output file (or NULL for standard output) */
1145 )
1146{
1147 SCIP_CONSDATA* consdata;
1148
1149 assert(scip != NULL);
1150 assert(cons != NULL);
1151
1152 consdata = SCIPconsGetData(cons);
1153 assert(consdata != NULL);
1154
1156
1157 /* print left hand side for ranged rows */
1158 if( !SCIPisInfinity(scip, -consdata->lhs)
1159 && !SCIPisInfinity(scip, consdata->rhs)
1160 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1161 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1162
1163 /* print coefficients and variables */
1164 if( consdata->nvars == 0 )
1165 SCIPinfoMessage(scip, file, "0");
1166 else
1167 {
1168 int v;
1169
1170 /* post linear sum of the linear constraint */
1171 for( v = 0; v < consdata->nvars; ++v )
1172 {
1173 if( consdata->vals != NULL )
1174 {
1175 if( consdata->vals[v] == 1.0 )
1176 {
1177 if( v > 0 )
1178 SCIPinfoMessage(scip, file, " +");
1179 }
1180 else if( consdata->vals[v] == -1.0 )
1181 SCIPinfoMessage(scip, file, " -");
1182 else
1183 SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1184 }
1185 else if( consdata->nvars > 0 )
1186 SCIPinfoMessage(scip, file, " +");
1187
1188 /* print variable name */
1189 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1190
1191 SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1192 }
1193 }
1194
1195 /* print right hand side */
1196 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1197 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1198 else if( !SCIPisInfinity(scip, consdata->rhs) )
1199 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1200 else if( !SCIPisInfinity(scip, -consdata->lhs) )
1201 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1202 else
1203 SCIPinfoMessage(scip, file, " [free]");
1204
1205 SCIPinfoMessage(scip, file, ";\n");
1206
1207 return SCIP_OKAY;
1208}
1209
1210/** invalidates activity bounds, such that they are recalculated in next get */
1211static
1213 SCIP_CONSDATA* consdata /**< linear constraint */
1214 )
1215{
1216 assert(consdata != NULL);
1217
1218 consdata->validactivities = FALSE;
1219 consdata->validminact = FALSE;
1220 consdata->validmaxact = FALSE;
1221 consdata->validglbminact = FALSE;
1222 consdata->validglbmaxact = FALSE;
1223 consdata->validmaxabsval = FALSE;
1224 consdata->validminabsval = FALSE;
1225 consdata->hasnonbinvalid = FALSE;
1226 QUAD_ASSIGN(consdata->minactivity, SCIP_INVALID);
1227 QUAD_ASSIGN(consdata->maxactivity, SCIP_INVALID);
1228 consdata->lastminactivity = SCIP_INVALID;
1229 consdata->lastmaxactivity = SCIP_INVALID;
1230 consdata->maxabsval = SCIP_INVALID;
1231 consdata->minabsval = SCIP_INVALID;
1232 consdata->maxactdelta = SCIP_INVALID;
1233 consdata->maxactdeltavar = NULL;
1234 consdata->minactivityneginf = -1;
1235 consdata->minactivityposinf = -1;
1236 consdata->maxactivityneginf = -1;
1237 consdata->maxactivityposinf = -1;
1238 consdata->minactivityneghuge = -1;
1239 consdata->minactivityposhuge = -1;
1240 consdata->maxactivityneghuge = -1;
1241 consdata->maxactivityposhuge = -1;
1242 QUAD_ASSIGN(consdata->glbminactivity, SCIP_INVALID);
1243 QUAD_ASSIGN(consdata->glbmaxactivity, SCIP_INVALID);
1244 consdata->lastglbminactivity = SCIP_INVALID;
1245 consdata->lastglbmaxactivity = SCIP_INVALID;
1246 consdata->glbminactivityneginf = -1;
1247 consdata->glbminactivityposinf = -1;
1248 consdata->glbmaxactivityneginf = -1;
1249 consdata->glbmaxactivityposinf = -1;
1250 consdata->glbminactivityneghuge = -1;
1251 consdata->glbminactivityposhuge = -1;
1252 consdata->glbmaxactivityneghuge = -1;
1253 consdata->glbmaxactivityposhuge = -1;
1254}
1255
1256/** compute the pseudo activity of a constraint */
1257static
1259 SCIP* scip, /**< SCIP data structure */
1260 SCIP_CONSDATA* consdata /**< linear constraint data */
1261 )
1262{
1263 int i;
1264 int pseudoactivityposinf;
1265 int pseudoactivityneginf;
1266 SCIP_Real pseudoactivity;
1268 SCIP_Real val;
1269
1270 pseudoactivity = 0;
1271 pseudoactivityposinf = 0;
1272 pseudoactivityneginf = 0;
1273
1274 for( i = consdata->nvars - 1; i >= 0; --i )
1275 {
1276 val = consdata->vals[i];
1277 bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1278 if( SCIPisInfinity(scip, bound) )
1279 {
1280 if( val > 0.0 )
1281 pseudoactivityposinf++;
1282 else
1283 pseudoactivityneginf++;
1284 }
1285 else
1286 {
1287 if( SCIPisInfinity(scip, -bound) )
1288 {
1289 if( val > 0.0 )
1290 pseudoactivityneginf++;
1291 else
1292 pseudoactivityposinf++;
1293 }
1294 else
1295 pseudoactivity += val * bound;
1296 }
1297 }
1298
1299 if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1300 return SCIP_INVALID;
1301 else if( pseudoactivityneginf > 0 )
1302 return -SCIPinfinity(scip);
1303 else if( pseudoactivityposinf > 0 )
1304 return SCIPinfinity(scip);
1305
1306 return pseudoactivity;
1307}
1308
1309/** recompute the minactivity of a constraint */
1310static
1312 SCIP* scip, /**< SCIP data structure */
1313 SCIP_CONSDATA* consdata /**< linear constraint data */
1314 )
1315{
1316 int i;
1318
1319 QUAD_ASSIGN(consdata->minactivity, 0.0);
1320
1321 for( i = consdata->nvars - 1; i >= 0; --i )
1322 {
1323 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1325 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1326 SCIPquadprecSumQD(consdata->minactivity, consdata->minactivity, consdata->vals[i] * bound);
1327 }
1328
1329 /* the activity was just computed from scratch and is valid now */
1330 consdata->validminact = TRUE;
1331
1332 /* the activity was just computed from scratch, mark it to be reliable */
1333 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
1334}
1335
1336/** recompute the maxactivity of a constraint */
1337static
1339 SCIP* scip, /**< SCIP data structure */
1340 SCIP_CONSDATA* consdata /**< linear constraint data */
1341 )
1342{
1343 int i;
1345
1346 QUAD_ASSIGN(consdata->maxactivity, 0.0);
1347
1348 for( i = consdata->nvars - 1; i >= 0; --i )
1349 {
1350 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1352 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1353 SCIPquadprecSumQD(consdata->maxactivity, consdata->maxactivity, consdata->vals[i] * bound);
1354 }
1355
1356 /* the activity was just computed from scratch and is valid now */
1357 consdata->validmaxact = TRUE;
1358
1359 /* the activity was just computed from scratch, mark it to be reliable */
1360 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
1361}
1362
1363/** recompute the global minactivity of a constraint */
1364static
1366 SCIP* scip, /**< SCIP data structure */
1367 SCIP_CONSDATA* consdata /**< linear constraint data */
1368 )
1369{
1370 int i;
1372
1373 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
1374
1375 for( i = consdata->nvars - 1; i >= 0; --i )
1376 {
1377 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1379 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1380 SCIPquadprecSumQD(consdata->glbminactivity, consdata->glbminactivity, consdata->vals[i] * bound);
1381 }
1382
1383 /* the activity was just computed from scratch and is valid now */
1384 consdata->validglbminact = TRUE;
1385
1386 /* the activity was just computed from scratch, mark it to be reliable */
1387 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
1388}
1389
1390/** recompute the global maxactivity of a constraint */
1391static
1393 SCIP* scip, /**< SCIP data structure */
1394 SCIP_CONSDATA* consdata /**< linear constraint data */
1395 )
1396{
1397 int i;
1399
1400 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
1401
1402 for( i = consdata->nvars - 1; i >= 0; --i )
1403 {
1404 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1406 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1407 SCIPquadprecSumQD(consdata->glbmaxactivity, consdata->glbmaxactivity, consdata->vals[i] * bound);
1408 }
1409
1410 /* the activity was just computed from scratch and is valid now */
1411 consdata->validglbmaxact = TRUE;
1412
1413 /* the activity was just computed from scratch, mark it to be reliable */
1414 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
1415}
1416
1417/** calculates maximum absolute value of coefficients */
1418static
1420 SCIP_CONSDATA* consdata /**< linear constraint data */
1421 )
1422{
1423 SCIP_Real absval;
1424 int i;
1425
1426 assert(consdata != NULL);
1427 assert(!consdata->validmaxabsval);
1428 assert(consdata->maxabsval >= SCIP_INVALID);
1429
1430 consdata->validmaxabsval = TRUE;
1431 consdata->maxabsval = 0.0;
1432 for( i = 0; i < consdata->nvars; ++i )
1433 {
1434 absval = consdata->vals[i];
1435 absval = REALABS(absval);
1436 if( absval > consdata->maxabsval )
1437 consdata->maxabsval = absval;
1438 }
1439}
1440
1441/** calculates minimum absolute value of coefficients */
1442static
1444 SCIP_CONSDATA* consdata /**< linear constraint data */
1445 )
1446{
1447 SCIP_Real absval;
1448 int i;
1449
1450 assert(consdata != NULL);
1451 assert(!consdata->validminabsval);
1452 assert(consdata->minabsval >= SCIP_INVALID);
1453
1454 consdata->validminabsval = TRUE;
1455
1456 if( consdata->nvars > 0 )
1457 consdata->minabsval = REALABS(consdata->vals[0]);
1458 else
1459 consdata->minabsval = 0.0;
1460
1461 for( i = 1; i < consdata->nvars; ++i )
1462 {
1463 absval = consdata->vals[i];
1464 absval = REALABS(absval);
1465 if( absval < consdata->minabsval )
1466 consdata->minabsval = absval;
1467 }
1468}
1469
1470/** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1471static
1473 SCIP_CONSDATA* consdata /**< linear constraint data */
1474 )
1475{
1476 int v;
1477
1478 assert(!consdata->hasnonbinvalid);
1479 consdata->hasnonbinvar = FALSE;
1480 consdata->hascontvar = FALSE;
1481
1482 for( v = consdata->nvars - 1; v >= 0; --v )
1483 {
1484 SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1485
1486 if( vartype != SCIP_VARTYPE_BINARY )
1487 {
1488 consdata->hasnonbinvar = TRUE;
1489
1490 if( vartype == SCIP_VARTYPE_CONTINUOUS )
1491 {
1492 consdata->hascontvar = TRUE;
1493 break;
1494 }
1495 }
1496 }
1497 assert(consdata->hascontvar || v < 0);
1498
1499 consdata->hasnonbinvalid = TRUE;
1500}
1501
1502
1503#ifdef CHECKMAXACTDELTA
1504/** checks that the stored maximal activity delta (if not invalid) is correct */
1505static
1507 SCIP* scip, /**< SCIP data structure */
1508 SCIP_CONSDATA* consdata /**< linear constraint data */
1509 )
1510{
1511 if( consdata->maxactdelta != SCIP_INVALID )
1512 {
1513 SCIP_Real maxactdelta = 0.0;
1514 SCIP_Real domain;
1515 SCIP_Real delta;
1516 SCIP_Real lb;
1517 SCIP_Real ub;
1518 int v;
1519
1520 for( v = consdata->nvars - 1; v >= 0; --v )
1521 {
1522 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1523 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1524
1525 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1526 {
1527 maxactdelta = SCIPinfinity(scip);
1528 break;
1529 }
1530
1531 domain = ub - lb;
1532 delta = REALABS(consdata->vals[v]) * domain;
1533
1534 if( delta > maxactdelta )
1535 {
1536 maxactdelta = delta;
1537 }
1538 }
1539 assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1540 }
1541}
1542#else
1543#define checkMaxActivityDelta(scip, consdata) /**/
1544#endif
1545
1546/** recompute maximal activity contribution for a single variable */
1547static
1549 SCIP* scip, /**< SCIP data structure */
1550 SCIP_CONSDATA* consdata /**< linear constraint data */
1551 )
1552{
1553 SCIP_Real delta;
1554 int v;
1555
1556 consdata->maxactdelta = 0.0;
1557
1558 if( !consdata->hasnonbinvalid )
1559 consdataCheckNonbinvar(consdata);
1560
1561 /* easy case, the problem consists only of binary variables */
1562 if( !consdata->hasnonbinvar )
1563 {
1564 for( v = consdata->nvars - 1; v >= 0; --v )
1565 {
1566 if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1567 {
1568 delta = REALABS(consdata->vals[v]);
1569
1570 if( delta > consdata->maxactdelta )
1571 {
1572 consdata->maxactdelta = delta;
1573 consdata->maxactdeltavar = consdata->vars[v];
1574 }
1575 }
1576 }
1577 return;
1578 }
1579
1580 for( v = consdata->nvars - 1; v >= 0; --v )
1581 {
1582 SCIP_Real domain;
1583 SCIP_Real lb;
1584 SCIP_Real ub;
1585
1586 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1587 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1588
1589 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1590 {
1591 consdata->maxactdelta = SCIPinfinity(scip);
1592 consdata->maxactdeltavar = consdata->vars[v];
1593 break;
1594 }
1595
1596 domain = ub - lb;
1597 delta = REALABS(consdata->vals[v]) * domain;
1598
1599 if( delta > consdata->maxactdelta )
1600 {
1601 consdata->maxactdelta = delta;
1602 consdata->maxactdeltavar = consdata->vars[v];
1603 }
1604 }
1605}
1606
1607
1608/** updates activities for a change in a bound */
1609static
1611 SCIP* scip, /**< SCIP data structure */
1612 SCIP_CONSDATA* consdata, /**< linear constraint data */
1613 SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1614 SCIP_Real oldbound, /**< old bound of variable */
1615 SCIP_Real newbound, /**< new bound of variable */
1616 SCIP_Real val, /**< coefficient of constraint entry */
1617 SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1618 SCIP_Bool global, /**< is it a global or a local bound change? */
1619 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1620 )
1621{
1622 QUAD_MEMBER(SCIP_Real* activity);
1623 QUAD_MEMBER(SCIP_Real delta);
1624 SCIP_Real* lastactivity;
1625 int* activityposinf;
1626 int* activityneginf;
1627 int* activityposhuge;
1628 int* activityneghuge;
1629 SCIP_Real oldcontribution;
1630 SCIP_Real newcontribution;
1631 SCIP_Bool validact;
1632 SCIP_Bool finitenewbound;
1633 SCIP_Bool hugevalnewcont;
1634
1635 assert(scip != NULL);
1636 assert(consdata != NULL);
1637 assert(global || (var != NULL));
1638 assert(consdata->validactivities);
1639 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
1640 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
1641 assert(consdata->lastminactivity < SCIP_INVALID);
1642 assert(consdata->lastmaxactivity < SCIP_INVALID);
1643 assert(consdata->minactivityneginf >= 0);
1644 assert(consdata->minactivityposinf >= 0);
1645 assert(consdata->maxactivityneginf >= 0);
1646 assert(consdata->maxactivityposinf >= 0);
1647 assert(consdata->minactivityneghuge >= 0);
1648 assert(consdata->minactivityposhuge >= 0);
1649 assert(consdata->maxactivityneghuge >= 0);
1650 assert(consdata->maxactivityposhuge >= 0);
1651 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
1652 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
1653 assert(consdata->lastglbminactivity < SCIP_INVALID);
1654 assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1655 assert(consdata->glbminactivityneginf >= 0);
1656 assert(consdata->glbminactivityposinf >= 0);
1657 assert(consdata->glbmaxactivityneginf >= 0);
1658 assert(consdata->glbmaxactivityposinf >= 0);
1659 assert(consdata->glbminactivityneghuge >= 0);
1660 assert(consdata->glbminactivityposhuge >= 0);
1661 assert(consdata->glbmaxactivityneghuge >= 0);
1662 assert(consdata->glbmaxactivityposhuge >= 0);
1663
1664 QUAD_ASSIGN(delta, 0.0);
1665
1666 /* we are updating global activities */
1667 if( global )
1668 {
1669 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1670 * lower bound + pos. coef: update minactivity
1671 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1672 * upper bound + pos. coef: update maxactivity
1673 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1674 */
1675 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1676 {
1677 if( val > 0.0 )
1678 {
1679 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1680 lastactivity = &(consdata->lastglbminactivity);
1681 activityposinf = &(consdata->glbminactivityposinf);
1682 activityneginf = &(consdata->glbminactivityneginf);
1683 activityposhuge = &(consdata->glbminactivityposhuge);
1684 activityneghuge = &(consdata->glbminactivityneghuge);
1685 validact = consdata->validglbminact;
1686 }
1687 else
1688 {
1689 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1690 lastactivity = &(consdata->lastglbmaxactivity);
1691 activityposinf = &(consdata->glbmaxactivityneginf);
1692 activityneginf = &(consdata->glbmaxactivityposinf);
1693 activityposhuge = &(consdata->glbmaxactivityposhuge);
1694 activityneghuge = &(consdata->glbmaxactivityneghuge);
1695 validact = consdata->validglbmaxact;
1696 }
1697 }
1698 else
1699 {
1700 if( val > 0.0 )
1701 {
1702 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1703 lastactivity = &(consdata->lastglbmaxactivity);
1704 activityposinf = &(consdata->glbmaxactivityposinf);
1705 activityneginf = &(consdata->glbmaxactivityneginf);
1706 activityposhuge = &(consdata->glbmaxactivityposhuge);
1707 activityneghuge = &(consdata->glbmaxactivityneghuge);
1708 validact = consdata->validglbmaxact;
1709 }
1710 else
1711 {
1712 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1713 lastactivity = &(consdata->lastglbminactivity);
1714 activityposinf = &(consdata->glbminactivityneginf);
1715 activityneginf = &(consdata->glbminactivityposinf);
1716 activityposhuge = &(consdata->glbminactivityposhuge);
1717 activityneghuge = &(consdata->glbminactivityneghuge);
1718 validact = consdata->validglbminact;
1719 }
1720 }
1721 }
1722 /* we are updating local activities */
1723 else
1724 {
1725 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1726 * lower bound + pos. coef: update minactivity
1727 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1728 * upper bound + pos. coef: update maxactivity
1729 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1730 */
1731 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1732 {
1733 if( val > 0.0 )
1734 {
1735 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1736 lastactivity = &(consdata->lastminactivity);
1737 activityposinf = &(consdata->minactivityposinf);
1738 activityneginf = &(consdata->minactivityneginf);
1739 activityposhuge = &(consdata->minactivityposhuge);
1740 activityneghuge = &(consdata->minactivityneghuge);
1741 validact = consdata->validminact;
1742 }
1743 else
1744 {
1745 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1746 lastactivity = &(consdata->lastmaxactivity);
1747 activityposinf = &(consdata->maxactivityneginf);
1748 activityneginf = &(consdata->maxactivityposinf);
1749 activityposhuge = &(consdata->maxactivityposhuge);
1750 activityneghuge = &(consdata->maxactivityneghuge);
1751 validact = consdata->validmaxact;
1752 }
1753 }
1754 else
1755 {
1756 if( val > 0.0 )
1757 {
1758 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1759 lastactivity = &(consdata->lastmaxactivity);
1760 activityposinf = &(consdata->maxactivityposinf);
1761 activityneginf = &(consdata->maxactivityneginf);
1762 activityposhuge = &(consdata->maxactivityposhuge);
1763 activityneghuge = &(consdata->maxactivityneghuge);
1764 validact = consdata->validmaxact;
1765 }
1766 else
1767 {
1768 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1769 lastactivity = &(consdata->lastminactivity);
1770 activityposinf = &(consdata->minactivityneginf);
1771 activityneginf = &(consdata->minactivityposinf);
1772 activityposhuge = &(consdata->minactivityposhuge);
1773 activityneghuge = &(consdata->minactivityneghuge);
1774 validact = consdata->validminact;
1775 }
1776 }
1777 }
1778
1779 oldcontribution = val * oldbound;
1780 newcontribution = val * newbound;
1781 hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1782 finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1783
1784 if( SCIPisInfinity(scip, REALABS(oldbound)) )
1785 {
1786 /* old bound was +infinity */
1787 if( oldbound > 0.0 )
1788 {
1789 assert((*activityposinf) >= 1);
1790
1791 /* we only have to do something if the new bound is not again +infinity */
1792 if( finitenewbound || newbound < 0.0 )
1793 {
1794 /* decrease the counter for positive infinite contributions */
1795 (*activityposinf)--;
1796
1797 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1798 if( !finitenewbound && newbound < 0.0 )
1799 (*activityneginf)++;
1800 else if( hugevalnewcont )
1801 {
1802 /* if the contribution of this variable is too large, increase the counter for huge values */
1803 if( newcontribution > 0.0 )
1804 (*activityposhuge)++;
1805 else
1806 (*activityneghuge)++;
1807 }
1808 /* "normal case": just add the contribution to the activity */
1809 else
1810 QUAD_ASSIGN(delta, newcontribution);
1811 }
1812 }
1813 /* old bound was -infinity */
1814 else
1815 {
1816 assert(oldbound < 0.0);
1817 assert((*activityneginf) >= 1);
1818
1819 /* we only have to do something ig the new bound is not again -infinity */
1820 if( finitenewbound || newbound > 0.0 )
1821 {
1822 /* decrease the counter for negative infinite contributions */
1823 (*activityneginf)--;
1824
1825 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1826 if( !finitenewbound && newbound > 0.0 )
1827 (*activityposinf)++;
1828 else if( hugevalnewcont )
1829 {
1830 /* if the contribution of this variable is too large, increase the counter for huge values */
1831 if( newcontribution > 0.0 )
1832 (*activityposhuge)++;
1833 else
1834 (*activityneghuge)++;
1835 }
1836 /* "normal case": just add the contribution to the activity */
1837 else
1838 QUAD_ASSIGN(delta, newcontribution);
1839 }
1840 }
1841 }
1842 else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1843 {
1844 /* old contribution was too large and positive */
1845 if( oldcontribution > 0.0 )
1846 {
1847 assert((*activityposhuge) >= 1);
1848
1849 /* decrease the counter for huge positive contributions; it might be increased again later,
1850 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1851 */
1852 (*activityposhuge)--;
1853
1854 if( !finitenewbound )
1855 {
1856 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1857 if( newbound > 0.0 )
1858 (*activityposinf)++;
1859 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1860 else
1861 (*activityneginf)++;
1862 }
1863 else if( hugevalnewcont )
1864 {
1865 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1866 if( newcontribution > 0.0 )
1867 (*activityposhuge)++;
1868 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1869 else
1870 (*activityneghuge)++;
1871 }
1872 /* "normal case": just add the contribution to the activity */
1873 else
1874 QUAD_ASSIGN(delta, newcontribution);
1875 }
1876 /* old contribution was too large and negative */
1877 else
1878 {
1879 assert(oldcontribution < 0.0);
1880 assert((*activityneghuge) >= 1);
1881
1882 /* decrease the counter for huge negative contributions; it might be increased again later,
1883 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1884 */
1885 (*activityneghuge)--;
1886
1887 if( !finitenewbound )
1888 {
1889 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1890 if( newbound > 0.0 )
1891 (*activityposinf)++;
1892 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1893 else
1894 (*activityneginf)++;
1895 }
1896 else if( hugevalnewcont )
1897 {
1898 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1899 if( newcontribution > 0.0 )
1900 (*activityposhuge)++;
1901 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1902 else
1903 (*activityneghuge)++;
1904 }
1905 /* "normal case": just add the contribution to the activity */
1906 else
1907 QUAD_ASSIGN(delta, newcontribution);
1908 }
1909 }
1910 /* old bound was finite and not too large */
1911 else
1912 {
1913 if( !finitenewbound )
1914 {
1915 /* if the new bound is +infinity, the old contribution has to be subtracted
1916 * and the counter for positive infinite contributions has to be increased
1917 */
1918 if( newbound > 0.0 )
1919 {
1920 (*activityposinf)++;
1921 QUAD_ASSIGN(delta, -oldcontribution);
1922 }
1923 /* if the new bound is -infinity, the old contribution has to be subtracted
1924 * and the counter for negative infinite contributions has to be increased
1925 */
1926 else
1927 {
1928 assert(newbound < 0.0 );
1929
1930 (*activityneginf)++;
1931 QUAD_ASSIGN(delta, -oldcontribution);
1932 }
1933 }
1934 /* if the contribution of this variable is too large, increase the counter for huge values */
1935 else if( hugevalnewcont )
1936 {
1937 if( newcontribution > 0.0 )
1938 {
1939 (*activityposhuge)++;
1940 QUAD_ASSIGN(delta, -oldcontribution);
1941 }
1942 else
1943 {
1944 (*activityneghuge)++;
1945 QUAD_ASSIGN(delta, -oldcontribution);
1946 }
1947 }
1948 /* "normal case": just update the activity */
1949 else
1950 {
1951 QUAD_ASSIGN(delta, newcontribution);
1952 SCIPquadprecSumQD(delta, delta, -oldcontribution);
1953 }
1954 }
1955
1956 /* update the activity, if the current value is valid and there was a change in the finite part */
1957 if( validact && (QUAD_TO_DBL(delta) != 0.0) )
1958 {
1959 SCIP_Real curractivity;
1960
1961 /* if the absolute value of the activity is increased, this is regarded as reliable,
1962 * otherwise, we check whether we can still trust the updated value
1963 */
1964 SCIPquadprecSumQD(*activity, *activity, QUAD_TO_DBL(delta));
1965
1966 curractivity = QUAD_TO_DBL(*activity);
1967 assert(!SCIPisInfinity(scip, -curractivity) && !SCIPisInfinity(scip, curractivity));
1968
1969 if( REALABS((*lastactivity)) < REALABS(curractivity) )
1970 {
1971 (*lastactivity) = curractivity;
1972 }
1973 else
1974 {
1975 if( checkreliability && SCIPisUpdateUnreliable(scip, curractivity, (*lastactivity)) )
1976 {
1977 SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1978 (global ? "global " : ""), curractivity);
1979
1980 /* mark the activity that was just changed and is not reliable anymore to be invalid */
1981 if( global )
1982 {
1983 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1984 consdata->validglbminact = FALSE;
1985 else
1986 consdata->validglbmaxact = FALSE;
1987 }
1988 else
1989 {
1990 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1991 consdata->validminact = FALSE;
1992 else
1993 consdata->validmaxact = FALSE;
1994 }
1995 }
1996 }
1997 }
1998}
1999
2000/** updates minimum and maximum activity for a change in lower bound */
2001static
2003 SCIP* scip, /**< SCIP data structure */
2004 SCIP_CONSDATA* consdata, /**< linear constraint data */
2005 SCIP_VAR* var, /**< variable that has been changed */
2006 SCIP_Real oldlb, /**< old lower bound of variable */
2007 SCIP_Real newlb, /**< new lower bound of variable */
2008 SCIP_Real val, /**< coefficient of constraint entry */
2009 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2010 )
2011{
2012 assert(scip != NULL);
2013 assert(consdata != NULL);
2014 assert(var != NULL);
2015
2016 if( consdata->validactivities )
2017 {
2018 consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
2019
2020 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2021 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2022 }
2023}
2024
2025/** updates minimum and maximum activity for a change in upper bound */
2026static
2028 SCIP* scip, /**< SCIP data structure */
2029 SCIP_CONSDATA* consdata, /**< linear constraint data */
2030 SCIP_VAR* var, /**< variable that has been changed */
2031 SCIP_Real oldub, /**< old upper bound of variable */
2032 SCIP_Real newub, /**< new upper bound of variable */
2033 SCIP_Real val, /**< coefficient of constraint entry */
2034 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2035 )
2036{
2037 assert(scip != NULL);
2038 assert(consdata != NULL);
2039 assert(var != NULL);
2040
2041 if( consdata->validactivities )
2042 {
2043 consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
2044
2045 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2046 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2047 }
2048}
2049
2050/** updates minimum and maximum global activity for a change in the global lower bound */
2051static
2053 SCIP* scip, /**< SCIP data structure */
2054 SCIP_CONSDATA* consdata, /**< linear constraint data */
2055 SCIP_Real oldlb, /**< old lower bound of variable */
2056 SCIP_Real newlb, /**< new lower bound of variable */
2057 SCIP_Real val, /**< coefficient of constraint entry */
2058 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2059 )
2060{
2061 assert(scip != NULL);
2062 assert(consdata != NULL);
2063
2064 if( consdata->validactivities )
2065 {
2066 consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2067
2068 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2069 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2070 }
2071}
2072
2073/** updates minimum and maximum global activity for a change in global upper bound */
2074static
2076 SCIP* scip, /**< SCIP data structure */
2077 SCIP_CONSDATA* consdata, /**< linear constraint data */
2078 SCIP_Real oldub, /**< old upper bound of variable */
2079 SCIP_Real newub, /**< new upper bound of variable */
2080 SCIP_Real val, /**< coefficient of constraint entry */
2081 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2082 )
2083{
2084 assert(scip != NULL);
2085 assert(consdata != NULL);
2086
2087 if( consdata->validactivities )
2088 {
2089 consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2090
2091 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2092 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2093 }
2094}
2095
2096/** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2097static
2099 SCIP* scip, /**< SCIP data structure */
2100 SCIP_CONSDATA* consdata, /**< linear constraint data */
2101 SCIP_VAR* var, /**< variable of constraint entry */
2102 SCIP_Real val, /**< coefficient of constraint entry */
2103 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2104 )
2105{
2106 assert(scip != NULL);
2107 assert(consdata != NULL);
2108 assert(var != NULL);
2109 assert(!SCIPisZero(scip, val));
2110
2111 /* update maximum absolute value */
2112 if( consdata->validmaxabsval )
2113 {
2114 SCIP_Real absval;
2115
2116 assert(consdata->maxabsval < SCIP_INVALID);
2117
2118 absval = REALABS(val);
2119 consdata->maxabsval = MAX(consdata->maxabsval, absval);
2120 }
2121
2122 /* update minimum absolute value */
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 minimum and maximum 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 /* update maximum activity delta */
2148 if( consdata->maxactdeltavar == NULL || !SCIPisInfinity(scip, consdata->maxactdelta) )
2149 {
2150 SCIP_Real lb = SCIPvarGetLbLocal(var);
2151 SCIP_Real ub = SCIPvarGetUbLocal(var);
2152
2153 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
2154 {
2155 consdata->maxactdelta = SCIPinfinity(scip);
2156 consdata->maxactdeltavar = var;
2157 }
2158 else if( consdata->maxactdeltavar != NULL )
2159 {
2160 SCIP_Real domain = ub - lb;
2161 SCIP_Real delta = REALABS(val) * domain;
2162
2163 if( delta > consdata->maxactdelta )
2164 {
2165 consdata->maxactdelta = delta;
2166 consdata->maxactdeltavar = var;
2167 }
2168 }
2169 }
2170}
2171
2172/** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2173static
2175 SCIP* scip, /**< SCIP data structure */
2176 SCIP_CONSDATA* consdata, /**< linear constraint data */
2177 SCIP_VAR* var, /**< variable of constraint entry */
2178 SCIP_Real val, /**< coefficient of constraint entry */
2179 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2180 )
2181{
2182 assert(scip != NULL);
2183 assert(consdata != NULL);
2184 assert(var != NULL);
2185 assert(!SCIPisZero(scip, val));
2186
2187 /* invalidate maximum absolute value, if this coefficient was the maximum */
2188 if( consdata->validmaxabsval )
2189 {
2190 SCIP_Real absval;
2191
2192 absval = REALABS(val);
2193
2194 if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2195 {
2196 consdata->validmaxabsval = FALSE;
2197 consdata->maxabsval = SCIP_INVALID;
2198 }
2199 }
2200
2201 /* invalidate minimum absolute value, if this coefficient was the minimum */
2202 if( consdata->validminabsval )
2203 {
2204 SCIP_Real absval;
2205
2206 absval = REALABS(val);
2207
2208 if( SCIPisEQ(scip, absval, consdata->minabsval) )
2209 {
2210 consdata->validminabsval = FALSE;
2211 consdata->minabsval = SCIP_INVALID;
2212 }
2213 }
2214
2215 /* update minimum and maximum activity */
2216 if( consdata->validactivities )
2217 {
2218 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2219 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2220 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2221 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2222
2223 consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2224 consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2225 consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2226 consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2227 }
2228
2229 /* reset maximum activity delta so that it will be recalculated on the next real propagation */
2230 if( consdata->maxactdeltavar == var )
2231 {
2232 consdata->maxactdelta = SCIP_INVALID;
2233 consdata->maxactdeltavar = NULL;
2234 }
2235}
2236
2237/** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2238static
2240 SCIP* scip, /**< SCIP data structure */
2241 SCIP_CONSDATA* consdata, /**< linear constraint data */
2242 SCIP_VAR* var, /**< variable of constraint entry */
2243 SCIP_Real oldval, /**< old coefficient of constraint entry */
2244 SCIP_Real newval, /**< new coefficient of constraint entry */
2245 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2246 )
2247{
2248 /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2249 consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2250 consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2251}
2252
2253/** returns the maximum absolute value of all coefficients in the constraint */
2254static
2256 SCIP_CONSDATA* consdata /**< linear constraint data */
2257 )
2258{
2259 assert(consdata != NULL);
2260
2261 if( !consdata->validmaxabsval )
2262 consdataCalcMaxAbsval(consdata);
2263 assert(consdata->validmaxabsval);
2264 assert(consdata->maxabsval < SCIP_INVALID);
2265
2266 return consdata->maxabsval;
2267}
2268
2269/** returns the minimum absolute value of all coefficients in the constraint */
2270static
2272 SCIP_CONSDATA* consdata /**< linear constraint data */
2273 )
2274{
2275 assert(consdata != NULL);
2276
2277 if( !consdata->validminabsval )
2278 consdataCalcMinAbsval(consdata);
2279 assert(consdata->validminabsval);
2280 assert(consdata->minabsval < SCIP_INVALID);
2281
2282 return consdata->minabsval;
2283}
2284
2285/** calculates minimum and maximum local and global activity for constraint from scratch;
2286 * additionally recalculates maximum absolute value of coefficients
2287 */
2288static
2290 SCIP* scip, /**< SCIP data structure */
2291 SCIP_CONSDATA* consdata /**< linear constraint data */
2292 )
2293{
2294 int i;
2295
2296 assert(scip != NULL);
2297 assert(consdata != NULL);
2298 assert(!consdata->validactivities);
2299 assert(QUAD_TO_DBL(consdata->minactivity) >= SCIP_INVALID || consdata->validminact);
2300 assert(QUAD_TO_DBL(consdata->maxactivity) >= SCIP_INVALID || consdata->validmaxact);
2301 assert(QUAD_TO_DBL(consdata->glbminactivity) >= SCIP_INVALID || consdata->validglbminact);
2302 assert(QUAD_TO_DBL(consdata->glbmaxactivity) >= SCIP_INVALID || consdata->validglbmaxact);
2303
2304 consdata->validmaxabsval = TRUE;
2305 consdata->validminabsval = TRUE;
2306 consdata->validactivities = TRUE;
2307 consdata->validminact = TRUE;
2308 consdata->validmaxact = TRUE;
2309 consdata->validglbminact = TRUE;
2310 consdata->validglbmaxact = TRUE;
2311 consdata->maxabsval = 0.0;
2312 consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2313 QUAD_ASSIGN(consdata->minactivity, 0.0);
2314 QUAD_ASSIGN(consdata->maxactivity, 0.0);
2315 consdata->lastminactivity = 0.0;
2316 consdata->lastmaxactivity = 0.0;
2317 consdata->minactivityneginf = 0;
2318 consdata->minactivityposinf = 0;
2319 consdata->maxactivityneginf = 0;
2320 consdata->maxactivityposinf = 0;
2321 consdata->minactivityneghuge = 0;
2322 consdata->minactivityposhuge = 0;
2323 consdata->maxactivityneghuge = 0;
2324 consdata->maxactivityposhuge = 0;
2325 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
2326 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
2327 consdata->lastglbminactivity = 0.0;
2328 consdata->lastglbmaxactivity = 0.0;
2329 consdata->glbminactivityneginf = 0;
2330 consdata->glbminactivityposinf = 0;
2331 consdata->glbmaxactivityneginf = 0;
2332 consdata->glbmaxactivityposinf = 0;
2333 consdata->glbminactivityneghuge = 0;
2334 consdata->glbminactivityposhuge = 0;
2335 consdata->glbmaxactivityneghuge = 0;
2336 consdata->glbmaxactivityposhuge = 0;
2337
2338 for( i = 0; i < consdata->nvars; ++i )
2339 consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2340
2341 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
2342 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
2343 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
2344 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2345}
2346
2347/** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2348 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2349 */
2350static
2352 SCIP* scip, /**< SCIP data structure */
2353 SCIP_CONSDATA* consdata, /**< linear constraint */
2354 int posinf, /**< number of coefficients contributing pos. infinite value */
2355 int neginf, /**< number of coefficients contributing neg. infinite value */
2356 int poshuge, /**< number of coefficients contributing huge pos. value */
2357 int neghuge, /**< number of coefficients contributing huge neg. value */
2358 SCIP_Real delta, /**< value to subtract from stored minactivity
2359 * (contribution of the variable set to zero when getting residual activity) */
2360 SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2361 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2362 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2363 SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
2364 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2365 SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2366 )
2367{
2368 assert(scip != NULL);
2369 assert(consdata != NULL);
2370 assert(posinf >= 0);
2371 assert(neginf >= 0);
2372 assert(poshuge >= 0);
2373 assert(neghuge >= 0);
2374 assert(minactivity != NULL);
2375 assert(istight != NULL);
2376 assert(issettoinfinity != NULL);
2377
2378 /* if we have neg. infinite contributions, the minactivity is -infty */
2379 if( neginf > 0 )
2380 {
2381 *minactivity = -SCIPinfinity(scip);
2382 *issettoinfinity = TRUE;
2383 *istight = posinf == 0;
2384 }
2385 /* if we have pos. (and no neg.) infinite contributions, the minactivity is +infty */
2386 else if( posinf > 0 )
2387 {
2388 *minactivity = SCIPinfinity(scip);
2389 *issettoinfinity = TRUE;
2390 *istight = TRUE;
2391 }
2392 /* if we have neg. huge contributions or do not need a good relaxation, we just return -infty as minactivity */
2393 else if( neghuge > 0 || ( poshuge > 0 && !goodrelax ) )
2394 {
2395 *minactivity = -SCIPinfinity(scip);
2396 *issettoinfinity = TRUE;
2397 *istight = FALSE;
2398 }
2399 else
2400 {
2401 SCIP_Real QUAD(tmpactivity);
2402
2403 /* recompute minactivity if it is not valid */
2404 if( global )
2405 {
2406 if( !consdata->validglbminact )
2408 assert(consdata->validglbminact);
2409
2410 QUAD_ASSIGN_Q(tmpactivity, consdata->glbminactivity);
2411 }
2412 else
2413 {
2414 if( !consdata->validminact )
2416 assert(consdata->validminact);
2417
2418 QUAD_ASSIGN_Q(tmpactivity, consdata->minactivity);
2419 }
2420
2421 /* calculate residual minactivity */
2422 SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
2423
2424 /* we have no infinite and no neg. huge contributions, but pos. huge contributions; a feasible relaxation of the
2425 * minactivity is given by adding the number of positive huge contributions times the huge value
2426 */
2427 if( poshuge > 0 )
2428 {
2429 SCIPquadprecSumQD(tmpactivity, tmpactivity, poshuge * SCIPgetHugeValue(scip));
2430 *istight = FALSE;
2431 }
2432 /* all counters are zero, so the minactivity is tight */
2433 else
2434 *istight = TRUE;
2435
2436 /* round residual minactivity */
2437 *minactivity = QUAD_TO_DBL(tmpactivity);
2438 *issettoinfinity = FALSE;
2439 }
2440}
2441
2442/** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2443 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2444 */
2445static
2447 SCIP* scip, /**< SCIP data structure */
2448 SCIP_CONSDATA* consdata, /**< linear constraint */
2449 int posinf, /**< number of coefficients contributing pos. infinite value */
2450 int neginf, /**< number of coefficients contributing neg. infinite value */
2451 int poshuge, /**< number of coefficients contributing huge pos. value */
2452 int neghuge, /**< number of coefficients contributing huge neg. value */
2453 SCIP_Real delta, /**< value to subtract from stored maxactivity
2454 * (contribution of the variable set to zero when getting residual activity) */
2455 SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2456 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2457 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2458 SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
2459 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2460 SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2461 )
2462{
2463 assert(scip != NULL);
2464 assert(consdata != NULL);
2465 assert(posinf >= 0);
2466 assert(neginf >= 0);
2467 assert(poshuge >= 0);
2468 assert(neghuge >= 0);
2469 assert(maxactivity != NULL);
2470 assert(istight != NULL);
2471 assert(issettoinfinity != NULL);
2472
2473 /* if we have pos. infinite contributions, the maxactivity is +infty */
2474 if( posinf > 0 )
2475 {
2476 *maxactivity = SCIPinfinity(scip);
2477 *issettoinfinity = TRUE;
2478 *istight = neginf == 0;
2479 }
2480 /* if we have neg. (and no pos.) infinite contributions, the maxactivity is -infty */
2481 else if( neginf > 0 )
2482 {
2483 *maxactivity = -SCIPinfinity(scip);
2484 *issettoinfinity = TRUE;
2485 *istight = TRUE;
2486 }
2487 /* if we have pos. huge contributions or do not need a good relaxation, we just return +infty as maxactivity */
2488 else if( poshuge > 0 || ( neghuge > 0 && !goodrelax ) )
2489 {
2490 *maxactivity = SCIPinfinity(scip);
2491 *issettoinfinity = TRUE;
2492 *istight = FALSE;
2493 }
2494 else
2495 {
2496 SCIP_Real QUAD(tmpactivity);
2497
2498 /* recompute maxactivity if it is not valid */
2499 if( global )
2500 {
2501 if( !consdata->validglbmaxact )
2503 assert(consdata->validglbmaxact);
2504
2505 QUAD_ASSIGN_Q(tmpactivity, consdata->glbmaxactivity);
2506 }
2507 else
2508 {
2509 if( !consdata->validmaxact )
2511 assert(consdata->validmaxact);
2512
2513 QUAD_ASSIGN_Q(tmpactivity, consdata->maxactivity);
2514 }
2515
2516 /* calculate residual maxactivity */
2517 SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
2518
2519 /* we have no infinite and no pos. huge contributions, but neg. huge contributions; a feasible relaxation of the
2520 * maxactivity is given by subtracting the number of negative huge contributions times the huge value
2521 */
2522 if( neghuge > 0 )
2523 {
2524 SCIPquadprecSumQD(tmpactivity, tmpactivity, -neghuge * SCIPgetHugeValue(scip));
2525 *istight = FALSE;
2526 }
2527 /* all counters are zero, so the maxactivity is tight */
2528 else
2529 *istight = TRUE;
2530
2531 /* round residual maxactivity */
2532 *maxactivity = QUAD_TO_DBL(tmpactivity);
2533 *issettoinfinity = FALSE;
2534 }
2535}
2536
2537/** gets activity bounds for constraint */
2538static
2540 SCIP* scip, /**< SCIP data structure */
2541 SCIP_CONSDATA* consdata, /**< linear constraint */
2542 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2543 * relaxed activities ignored, anyway? */
2544 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2545 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2546 SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
2547 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2548 SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
2549 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2550 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2551 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2552
2553 )
2554{
2555 assert(scip != NULL);
2556 assert(consdata != NULL);
2557 assert(minactivity != NULL);
2558 assert(maxactivity != NULL);
2559 assert(isminsettoinfinity != NULL);
2560 assert(ismaxsettoinfinity != NULL);
2561
2562 if( !consdata->validactivities )
2563 {
2564 consdataCalcActivities(scip, consdata);
2565 assert(consdata->validminact);
2566 assert(consdata->validmaxact);
2567 }
2568 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2569 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2570 assert(consdata->minactivityneginf >= 0);
2571 assert(consdata->minactivityposinf >= 0);
2572 assert(consdata->maxactivityneginf >= 0);
2573 assert(consdata->maxactivityposinf >= 0);
2574
2575 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2576 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2577 minactivity, ismintight, isminsettoinfinity);
2578
2579 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2580 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2581 maxactivity, ismaxtight, ismaxsettoinfinity);
2582}
2583
2584/** calculates activity bounds for constraint after setting variable to zero */
2585static
2587 SCIP* scip, /**< SCIP data structure */
2588 SCIP_CONSDATA* consdata, /**< linear constraint */
2589 SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2590 SCIP_Real* resactivity, /**< pointer to store the residual activity */
2591 SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2592 SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2593 )
2594{
2595 SCIP_VAR* var;
2596 SCIP_Real val;
2597 SCIP_Real lb;
2598 SCIP_Real ub;
2599 int v;
2600
2601 assert(scip != NULL);
2602 assert(consdata != NULL);
2603 assert(cancelvar != NULL);
2604 assert(resactivity != NULL);
2605
2606 *resactivity = 0.0;
2607
2608 for( v = 0; v < consdata->nvars; ++v )
2609 {
2610 var = consdata->vars[v];
2611 assert(var != NULL);
2612 if( var == cancelvar )
2613 continue;
2614
2615 val = consdata->vals[v];
2616
2617 if( useglobalbounds )
2618 {
2619 lb = SCIPvarGetLbGlobal(var);
2620 ub = SCIPvarGetUbGlobal(var);
2621 }
2622 else
2623 {
2624 lb = SCIPvarGetLbLocal(var);
2625 ub = SCIPvarGetUbLocal(var);
2626 }
2627
2628 assert(!SCIPisZero(scip, val));
2629 assert(SCIPisLE(scip, lb, ub));
2630
2631 if( val > 0.0 )
2632 {
2633 if( isminresact )
2634 {
2635 assert(!SCIPisInfinity(scip, -lb));
2636 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2637 *resactivity += val*lb;
2638 }
2639 else
2640 {
2641 assert(!SCIPisInfinity(scip, ub));
2642 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2643 *resactivity += val*ub;
2644 }
2645 }
2646 else
2647 {
2648 if( isminresact)
2649 {
2650 assert(!SCIPisInfinity(scip, ub));
2651 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2652 *resactivity += val*ub;
2653 }
2654 else
2655 {
2656 assert(!SCIPisInfinity(scip, -lb));
2657 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2658 *resactivity += val*lb;
2659 }
2660 }
2661 }
2662 assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2663}
2664
2665/** gets activity bounds for constraint after setting variable to zero */
2666static
2668 SCIP* scip, /**< SCIP data structure */
2669 SCIP_CONSDATA* consdata, /**< linear constraint */
2670 SCIP_VAR* var, /**< variable to calculate activity residual for */
2671 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2672 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2673 * relaxed acticities ignored, anyway? */
2674 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2675 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2676 SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
2677 * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
2678 SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
2679 * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
2680 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2681 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2682 )
2683{
2684 SCIP_Real minactbound;
2685 SCIP_Real maxactbound;
2686 SCIP_Real absval;
2687
2688 assert(scip != NULL);
2689 assert(consdata != NULL);
2690 assert(var != NULL);
2691 assert(minresactivity != NULL);
2692 assert(maxresactivity != NULL);
2693 assert(ismintight != NULL);
2694 assert(ismaxtight != NULL);
2695 assert(isminsettoinfinity != NULL);
2696 assert(ismaxsettoinfinity != NULL);
2697
2698 /* get activity bounds of linear constraint */
2699 if( !consdata->validactivities )
2700 {
2701 consdataCalcActivities(scip, consdata);
2702 assert(consdata->validminact);
2703 assert(consdata->validmaxact);
2704 }
2705 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2706 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2707 assert(consdata->minactivityneginf >= 0);
2708 assert(consdata->minactivityposinf >= 0);
2709 assert(consdata->maxactivityneginf >= 0);
2710 assert(consdata->maxactivityposinf >= 0);
2711 assert(consdata->minactivityneghuge >= 0);
2712 assert(consdata->minactivityposhuge >= 0);
2713 assert(consdata->maxactivityneghuge >= 0);
2714 assert(consdata->maxactivityposhuge >= 0);
2715
2716 if( val > 0.0 )
2717 {
2718 minactbound = SCIPvarGetLbLocal(var);
2719 maxactbound = SCIPvarGetUbLocal(var);
2720 absval = val;
2721 }
2722 else
2723 {
2724 minactbound = -SCIPvarGetUbLocal(var);
2725 maxactbound = -SCIPvarGetLbLocal(var);
2726 absval = -val;
2727 }
2728
2729 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2730 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2731 */
2732 if( SCIPisInfinity(scip, minactbound) )
2733 {
2734 assert(consdata->minactivityposinf >= 1);
2735
2736 getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2737 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2738 minresactivity, ismintight, isminsettoinfinity);
2739 }
2740 else if( SCIPisInfinity(scip, -minactbound) )
2741 {
2742 assert(consdata->minactivityneginf >= 1);
2743
2744 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2745 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2746 minresactivity, ismintight, isminsettoinfinity);
2747 }
2748 else if( SCIPisHugeValue(scip, minactbound * absval) )
2749 {
2750 assert(consdata->minactivityposhuge >= 1);
2751
2752 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2753 consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2754 minresactivity, ismintight, isminsettoinfinity);
2755 }
2756 else if( SCIPisHugeValue(scip, -minactbound * absval) )
2757 {
2758 assert(consdata->minactivityneghuge >= 1);
2759
2760 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2761 consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2762 minresactivity, ismintight, isminsettoinfinity);
2763 }
2764 else
2765 {
2766 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2767 consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2768 minresactivity, ismintight, isminsettoinfinity);
2769 }
2770
2771 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2772 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2773 */
2774 if( SCIPisInfinity(scip, -maxactbound) )
2775 {
2776 assert(consdata->maxactivityneginf >= 1);
2777
2778 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2779 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2780 maxresactivity, ismaxtight, ismaxsettoinfinity);
2781 }
2782 else if( SCIPisInfinity(scip, maxactbound) )
2783 {
2784 assert(consdata->maxactivityposinf >= 1);
2785
2786 getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2787 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2788 maxresactivity, ismaxtight, ismaxsettoinfinity);
2789 }
2790 else if( SCIPisHugeValue(scip, absval * maxactbound) )
2791 {
2792 assert(consdata->maxactivityposhuge >= 1);
2793
2794 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2795 consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2796 maxresactivity, ismaxtight, ismaxsettoinfinity);
2797 }
2798 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2799 {
2800 assert(consdata->maxactivityneghuge >= 1);
2801
2802 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2803 consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2804 maxresactivity, ismaxtight, ismaxsettoinfinity);
2805 }
2806 else
2807 {
2808 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2809 consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2810 maxresactivity, ismaxtight, ismaxsettoinfinity);
2811 }
2812}
2813
2814/** gets global activity bounds for constraint */
2815static
2817 SCIP* scip, /**< SCIP data structure */
2818 SCIP_CONSDATA* consdata, /**< linear constraint */
2819 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2820 * relaxed acticities ignored, anyway? */
2821 SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2822 SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2823 SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
2824 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2825 SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
2826 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2827 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2828 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2829 )
2830{
2831 assert(scip != NULL);
2832 assert(consdata != NULL);
2833 assert((glbminactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL)
2834 || (glbmaxactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
2835
2836 if( !consdata->validactivities )
2837 {
2838 consdataCalcActivities(scip, consdata);
2839 assert(consdata->validglbminact);
2840 assert(consdata->validglbmaxact);
2841 }
2842 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2843 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2844 assert(consdata->glbminactivityneginf >= 0);
2845 assert(consdata->glbminactivityposinf >= 0);
2846 assert(consdata->glbmaxactivityneginf >= 0);
2847 assert(consdata->glbmaxactivityposinf >= 0);
2848 assert(consdata->glbminactivityneghuge >= 0);
2849 assert(consdata->glbminactivityposhuge >= 0);
2850 assert(consdata->glbmaxactivityneghuge >= 0);
2851 assert(consdata->glbmaxactivityposhuge >= 0);
2852
2853 if( glbminactivity != NULL )
2854 {
2855 assert(isminsettoinfinity != NULL);
2856 assert(ismintight != NULL);
2857
2858 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2859 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2860 glbminactivity, ismintight, isminsettoinfinity);
2861 }
2862
2863 if( glbmaxactivity != NULL )
2864 {
2865 assert(ismaxsettoinfinity != NULL);
2866 assert(ismaxtight != NULL);
2867
2868 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2869 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2870 glbmaxactivity, ismaxtight, ismaxsettoinfinity);
2871 }
2872}
2873
2874/** gets global activity bounds for constraint after setting variable to zero */
2875static
2877 SCIP* scip, /**< SCIP data structure */
2878 SCIP_CONSDATA* consdata, /**< linear constraint */
2879 SCIP_VAR* var, /**< variable to calculate activity residual for */
2880 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2881 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2882 * relaxed acticities ignored, anyway? */
2883 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2884 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2885 SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
2886 * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
2887 SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
2888 * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
2889 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2890 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2891 )
2892{
2893 SCIP_Real minactbound;
2894 SCIP_Real maxactbound;
2895 SCIP_Real absval;
2896
2897 assert(scip != NULL);
2898 assert(consdata != NULL);
2899 assert(var != NULL);
2900 assert((minresactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL )
2901 || (maxresactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
2902
2903 /* get activity bounds of linear constraint */
2904 if( !consdata->validactivities )
2905 consdataCalcActivities(scip, consdata);
2906
2907 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2908 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2909 assert(consdata->glbminactivityneginf >= 0);
2910 assert(consdata->glbminactivityposinf >= 0);
2911 assert(consdata->glbmaxactivityneginf >= 0);
2912 assert(consdata->glbmaxactivityposinf >= 0);
2913
2914 if( val > 0.0 )
2915 {
2916 minactbound = SCIPvarGetLbGlobal(var);
2917 maxactbound = SCIPvarGetUbGlobal(var);
2918 absval = val;
2919 }
2920 else
2921 {
2922 minactbound = -SCIPvarGetUbGlobal(var);
2923 maxactbound = -SCIPvarGetLbGlobal(var);
2924 absval = -val;
2925 }
2926
2927 if( minresactivity != NULL )
2928 {
2929 assert(isminsettoinfinity != NULL);
2930 assert(ismintight != NULL);
2931
2932 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2933 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2934 */
2935 if( SCIPisInfinity(scip, minactbound) )
2936 {
2937 assert(consdata->glbminactivityposinf >= 1);
2938
2939 getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2940 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2941 minresactivity, ismintight, isminsettoinfinity);
2942 }
2943 else if( SCIPisInfinity(scip, -minactbound) )
2944 {
2945 assert(consdata->glbminactivityneginf >= 1);
2946
2947 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2948 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2949 minresactivity, ismintight, isminsettoinfinity);
2950 }
2951 else if( SCIPisHugeValue(scip, minactbound * absval) )
2952 {
2953 assert(consdata->glbminactivityposhuge >= 1);
2954
2955 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2956 consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2957 minresactivity, ismintight, isminsettoinfinity);
2958 }
2959 else if( SCIPisHugeValue(scip, -minactbound * absval) )
2960 {
2961 assert(consdata->glbminactivityneghuge >= 1);
2962
2963 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2964 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
2965 minresactivity, ismintight, isminsettoinfinity);
2966 }
2967 else
2968 {
2969 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2970 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
2971 goodrelax, minresactivity, ismintight, isminsettoinfinity);
2972 }
2973 }
2974
2975 if( maxresactivity != NULL )
2976 {
2977 assert(ismaxsettoinfinity != NULL);
2978 assert(ismaxtight != NULL);
2979
2980 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2981 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2982 */
2983 if( SCIPisInfinity(scip, -maxactbound) )
2984 {
2985 assert(consdata->glbmaxactivityneginf >= 1);
2986
2987 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
2988 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2989 maxresactivity, ismaxtight, ismaxsettoinfinity);
2990 }
2991 else if( SCIPisInfinity(scip, maxactbound) )
2992 {
2993 assert(consdata->glbmaxactivityposinf >= 1);
2994
2995 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
2996 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2997 maxresactivity, ismaxtight, ismaxsettoinfinity);
2998 }
2999 else if( SCIPisHugeValue(scip, absval * maxactbound) )
3000 {
3001 assert(consdata->glbmaxactivityposhuge >= 1);
3002
3003 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3004 consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3005 maxresactivity, ismaxtight, ismaxsettoinfinity);
3006 }
3007 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3008 {
3009 assert(consdata->glbmaxactivityneghuge >= 1);
3010
3011 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3012 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3013 maxresactivity, ismaxtight, ismaxsettoinfinity);
3014 }
3015 else
3016 {
3017 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3018 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3019 goodrelax, maxresactivity, ismaxtight, ismaxsettoinfinity);
3020 }
3021 }
3022}
3023
3024/** calculates the activity of the linear constraint for given solution */
3025static
3027 SCIP* scip, /**< SCIP data structure */
3028 SCIP_CONSDATA* consdata, /**< linear constraint data */
3029 SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3030 )
3031{
3032 SCIP_Real activity;
3033
3034 assert(scip != NULL);
3035 assert(consdata != NULL);
3036
3037 if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3038 activity = consdataComputePseudoActivity(scip, consdata);
3039 else
3040 {
3041 SCIP_Real solval;
3042 int nposinf;
3043 int nneginf;
3044 SCIP_Bool negsign;
3045 int v;
3046
3047 activity = 0.0;
3048 nposinf = 0;
3049 nneginf = 0;
3050
3051 for( v = 0; v < consdata->nvars; ++v )
3052 {
3053 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3054
3055 if( consdata->vals[v] < 0 )
3056 negsign = TRUE;
3057 else
3058 negsign = FALSE;
3059
3060 if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3061 ++nposinf;
3062 else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3063 ++nneginf;
3064 else
3065 activity += consdata->vals[v] * solval;
3066 }
3067 assert(nneginf >= 0 && nposinf >= 0);
3068
3069 SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3070
3071 /* check for amount of infinity values and correct the activity */
3072 if( nposinf > 0 && nneginf > 0 )
3073 activity = (consdata->rhs + consdata->lhs) / 2;
3074 else if( nposinf > 0 )
3075 activity = SCIPinfinity(scip);
3076 else if( nneginf > 0 )
3077 activity = -SCIPinfinity(scip);
3078
3079 SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3080 }
3081
3082 if( activity == SCIP_INVALID ) /*lint !e777*/
3083 return activity;
3084 else if( activity < 0 )
3085 activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3086 else
3087 activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3088
3089 return activity;
3090}
3091
3092/** calculates the feasibility of the linear constraint for given solution */
3093static
3095 SCIP* scip, /**< SCIP data structure */
3096 SCIP_CONSDATA* consdata, /**< linear constraint data */
3097 SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3098 )
3099{
3100 SCIP_Real activity;
3101
3102 assert(scip != NULL);
3103 assert(consdata != NULL);
3104
3105 activity = consdataGetActivity(scip, consdata, sol);
3106
3107 if( activity == SCIP_INVALID ) /*lint !e777*/
3108 return -SCIPinfinity(scip);
3109
3110 return MIN(consdata->rhs - activity, activity - consdata->lhs);
3111}
3112
3113/** updates bit signatures after adding a single coefficient */
3114static
3116 SCIP_CONSDATA* consdata, /**< linear constraint data */
3117 int pos /**< position of coefficient to update signatures for */
3118 )
3119{
3120 uint64_t varsignature;
3121 SCIP_Real lb;
3122 SCIP_Real ub;
3123 SCIP_Real val;
3124
3125 assert(consdata != NULL);
3126 assert(consdata->validsignature);
3127
3128 varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3129 lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3130 ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3131 val = consdata->vals[pos];
3132 if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3133 consdata->possignature |= varsignature;
3134 if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3135 consdata->negsignature |= varsignature;
3136}
3137
3138/** calculates the bit signatures of the given constraint data */
3139static
3141 SCIP_CONSDATA* consdata /**< linear constraint data */
3142 )
3143{
3144 assert(consdata != NULL);
3145
3146 if( !consdata->validsignature )
3147 {
3148 int i;
3149
3150 consdata->validsignature = TRUE;
3151 consdata->possignature = 0;
3152 consdata->negsignature = 0;
3153 for( i = 0; i < consdata->nvars; ++i )
3154 consdataUpdateSignatures(consdata, i);
3155 }
3156}
3157
3158/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3159static
3161{ /*lint --e{715}*/
3162 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3163 SCIP_VAR* var1;
3164 SCIP_VAR* var2;
3165
3166 assert(consdata != NULL);
3167 assert(0 <= ind1 && ind1 < consdata->nvars);
3168 assert(0 <= ind2 && ind2 < consdata->nvars);
3169
3170 var1 = consdata->vars[ind1];
3171 var2 = consdata->vars[ind2];
3172
3173 /* exactly one variable is binary */
3174 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3175 {
3176 return (SCIPvarIsBinary(var1) ? -1 : +1);
3177 }
3178 /* both variables are binary */
3179 else if( SCIPvarIsBinary(var1) )
3180 {
3181 return SCIPvarCompare(var1, var2);
3182 }
3183 else
3184 {
3185 SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3186 SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3187
3188 if( vartype1 < vartype2 )
3189 return -1;
3190 else if( vartype1 > vartype2 )
3191 return +1;
3192 else
3193 return SCIPvarCompare(var1, var2);
3194 }
3195}
3196
3197/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3198static
3199SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
3200{ /*lint --e{715}*/
3201 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3202 SCIP_VAR* var1;
3203 SCIP_VAR* var2;
3204
3205 assert(consdata != NULL);
3206 assert(0 <= ind1 && ind1 < consdata->nvars);
3207 assert(0 <= ind2 && ind2 < consdata->nvars);
3208
3209 var1 = consdata->vars[ind1];
3210 var2 = consdata->vars[ind2];
3211
3212 /* exactly one variable is binary */
3213 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3214 {
3215 return (SCIPvarIsBinary(var1) ? -1 : +1);
3216 }
3217 /* both variables are binary */
3218 else if( SCIPvarIsBinary(var1) )
3219 {
3220 SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3221 SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3222
3223 if( EPSGT(abscoef1, abscoef2, 1e-9) )
3224 return -1;
3225 else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3226 return +1;
3227 else
3228 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3229 }
3230 else
3231 {
3232 SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3233 SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3234
3235 if( vartype1 < vartype2 )
3236 {
3237 return -1;
3238 }
3239 else if( vartype1 > vartype2 )
3240 {
3241 return +1;
3242 }
3243 else
3244 {
3245 /* both variables are continuous */
3246 if( !SCIPvarIsIntegral(var1) )
3247 {
3248 assert(!SCIPvarIsIntegral(var2));
3249 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3250 }
3251 else
3252 {
3253 SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3254 SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3255
3256 if( EPSGT(abscont1, abscont2, 1e-9) )
3257 return -1;
3258 else if( EPSGT(abscont2, abscont1, 1e-9) )
3259 return +1;
3260 else
3261 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3262 }
3263 }
3264 }
3265}
3266
3267/** permutes the constraint's variables according to a given permutation. */
3268static
3270 SCIP_CONSDATA* consdata, /**< the constraint data */
3271 int* perm, /**< the target permutation */
3272 int nvars /**< the number of variables */
3273 )
3274{ /*lint --e{715}*/
3275 SCIP_VAR* varv;
3276 SCIP_EVENTDATA* eventdatav;
3277 SCIP_Real valv;
3278 int v;
3279 int i;
3280 int nexti;
3281
3282 assert(perm != NULL);
3283 assert(consdata != NULL);
3284
3285 /* permute the variables in the linear constraint according to the target permutation */
3286 eventdatav = NULL;
3287 for( v = 0; v < nvars; ++v )
3288 {
3289 if( perm[v] != v )
3290 {
3291 varv = consdata->vars[v];
3292 valv = consdata->vals[v];
3293 if( consdata->eventdata != NULL )
3294 eventdatav = consdata->eventdata[v];
3295 i = v;
3296 do
3297 {
3298 assert(0 <= perm[i] && perm[i] < nvars);
3299 assert(perm[i] != i);
3300 consdata->vars[i] = consdata->vars[perm[i]];
3301 consdata->vals[i] = consdata->vals[perm[i]];
3302 if( consdata->eventdata != NULL )
3303 {
3304 consdata->eventdata[i] = consdata->eventdata[perm[i]];
3305 consdata->eventdata[i]->varpos = i;
3306 }
3307 nexti = perm[i];
3308 perm[i] = i;
3309 i = nexti;
3310 }
3311 while( perm[i] != v );
3312 consdata->vars[i] = varv;
3313 consdata->vals[i] = valv;
3314 if( consdata->eventdata != NULL )
3315 {
3316 consdata->eventdata[i] = eventdatav;
3317 consdata->eventdata[i]->varpos = i;
3318 }
3319 perm[i] = i;
3320 }
3321 }
3322#ifdef SCIP_DEBUG
3323 /* check sorting */
3324 for( v = 0; v < nvars; ++v )
3325 {
3326 assert(perm[v] == v);
3327 assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3328 }
3329#endif
3330}
3331
3332/** sorts linear constraint's variables depending on the stage of the solving process:
3333 * - during PRESOLVING
3334 * sorts variables by binaries, integers, implicit integers, and continuous variables,
3335 * and the variables of the same type by non-decreasing variable index
3336 *
3337 * - during SOLVING
3338 * sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables,
3339 * and binary and integer variables by their global max activity delta (within each group),
3340 * ties within a group are broken by problem index of the variable.
3341 *
3342 * This fastens the propagation time of the constraint handler.
3343 */
3344static
3346 SCIP* scip, /**< SCIP data structure */
3347 SCIP_CONSDATA* consdata /**< linear constraint data */
3348 )
3349{
3350 assert(scip != NULL);
3351 assert(consdata != NULL);
3352
3353 /* check if there are variables for sorting */
3354 if( consdata->nvars <= 1 )
3355 {
3356 consdata->indexsorted = TRUE;
3357 consdata->coefsorted = TRUE;
3358 consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3359 }
3360 else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3361 || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3362 {
3363 int* perm;
3364 int v;
3365
3366 /* get temporary memory to store the sorted permutation */
3367 SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3368
3369 /* call sorting method */
3371 SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3372 else
3373 SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3374
3375 permSortConsdata(consdata, perm, consdata->nvars);
3376
3377 /* free temporary memory */
3378 SCIPfreeBufferArray(scip, &perm);
3379
3381 {
3382 consdata->indexsorted = FALSE;
3383 consdata->coefsorted = TRUE;
3384
3385 /* count binary variables in the sorted vars array */
3386 consdata->nbinvars = 0;
3387 for( v = 0; v < consdata->nvars; ++v )
3388 {
3389 if( SCIPvarIsBinary(consdata->vars[v]) )
3390 ++consdata->nbinvars;
3391 else
3392 break;
3393 }
3394 }
3395 else
3396 {
3397 consdata->indexsorted = TRUE;
3398 consdata->coefsorted = FALSE;
3399 }
3400 }
3401
3402 return SCIP_OKAY;
3403}
3404
3405
3406/*
3407 * local linear constraint handler methods
3408 */
3409
3410/** sets left hand side of linear constraint */
3411static
3413 SCIP* scip, /**< SCIP data structure */
3414 SCIP_CONS* cons, /**< linear constraint */
3415 SCIP_Real lhs /**< new left hand side */
3416 )
3417{
3418 SCIP_CONSDATA* consdata;
3419 SCIP_Bool locked;
3420 int i;
3421
3422 assert(scip != NULL);
3423 assert(cons != NULL);
3424
3425 /* adjust value to be not beyond infinity */
3426 if( SCIPisInfinity(scip, -lhs) )
3427 lhs = -SCIPinfinity(scip);
3428 else if( SCIPisInfinity(scip, lhs) )
3429 lhs = SCIPinfinity(scip);
3430
3431 consdata = SCIPconsGetData(cons);
3432 assert(consdata != NULL);
3433 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3434
3435 /* check whether the side is not changed */
3436 if( SCIPisEQ(scip, consdata->lhs, lhs) )
3437 return SCIP_OKAY;
3438
3439 assert(!SCIPisInfinity(scip, ABS(consdata->lhs)) || !SCIPisInfinity(scip, ABS(lhs)));
3440
3441 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3442 if( SCIPisEQ(scip, lhs, consdata->rhs) )
3443 {
3444 consdata->rhs = lhs;
3445 assert(consdata->row == NULL);
3446 }
3447
3448 locked = FALSE;
3449 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3450 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3451
3452 /* if necessary, update the rounding locks of variables */
3453 if( locked )
3454 {
3455 if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3456 {
3457 SCIP_VAR** vars;
3458 SCIP_Real* vals;
3459 int v;
3460
3461 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3462 vars = consdata->vars;
3463 vals = consdata->vals;
3464
3465 for( v = 0; v < consdata->nvars; ++v )
3466 {
3467 assert(vars[v] != NULL);
3468 assert(!SCIPisZero(scip, vals[v]));
3469
3470 if( SCIPisPositive(scip, vals[v]) )
3471 {
3472 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3473 }
3474 else
3475 {
3476 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3477 }
3478 }
3479 }
3480 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3481 {
3482 SCIP_VAR** vars;
3483 SCIP_Real* vals;
3484 int v;
3485
3486 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3487 vars = consdata->vars;
3488 vals = consdata->vals;
3489
3490 for( v = 0; v < consdata->nvars; ++v )
3491 {
3492 assert(vars[v] != NULL);
3493 assert(!SCIPisZero(scip, vals[v]));
3494
3495 if( SCIPisPositive(scip, vals[v]) )
3496 {
3497 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3498 }
3499 else
3500 {
3501 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3502 }
3503 }
3504 }
3505 }
3506
3507 /* 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 */
3508 if( !SCIPisInfinity(scip, ABS(lhs)) && SCIPisGT(scip, lhs, consdata->lhs) )
3509 {
3510 consdata->boundstightened = 0;
3511 consdata->presolved = FALSE;
3512 consdata->cliquesadded = FALSE;
3513 consdata->implsadded = FALSE;
3514
3515 /* mark the constraint for propagation */
3516 if( SCIPconsIsTransformed(cons) )
3517 {
3519 }
3520 }
3521
3522 /* set new left hand side and update constraint data */
3523 consdata->lhs = lhs;
3524 consdata->changed = TRUE;
3525 consdata->normalized = FALSE;
3526 consdata->upgradetried = FALSE;
3527 consdata->rangedrowpropagated = 0;
3528
3529 /* update the lhs of the LP row */
3530 if( consdata->row != NULL )
3531 {
3532 SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3533 }
3534
3535 return SCIP_OKAY;
3536}
3537
3538/** sets right hand side of linear constraint */
3539static
3541 SCIP* scip, /**< SCIP data structure */
3542 SCIP_CONS* cons, /**< linear constraint */
3543 SCIP_Real rhs /**< new right hand side */
3544 )
3545{
3546 SCIP_CONSDATA* consdata;
3547 SCIP_Bool locked;
3548 int i;
3549
3550 assert(scip != NULL);
3551 assert(cons != NULL);
3552
3553 /* adjust value to be not beyond infinity */
3554 if( SCIPisInfinity(scip, rhs) )
3555 rhs = SCIPinfinity(scip);
3556 else if( SCIPisInfinity(scip, -rhs) )
3557 rhs = -SCIPinfinity(scip);
3558
3559 consdata = SCIPconsGetData(cons);
3560 assert(consdata != NULL);
3561 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3562
3563 /* check whether the side is not changed */
3564 if( SCIPisEQ(scip, consdata->rhs, rhs) )
3565 return SCIP_OKAY;
3566
3567 assert(!SCIPisInfinity(scip, ABS(consdata->rhs)) || !SCIPisInfinity(scip, ABS(rhs)));
3568
3569 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3570 if( SCIPisEQ(scip, rhs, consdata->lhs) )
3571 {
3572 consdata->lhs = rhs;
3573 assert(consdata->row == NULL);
3574 }
3575
3576 locked = FALSE;
3577 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3578 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3579
3580 /* if necessary, update the rounding locks of variables */
3581 if( locked )
3582 {
3583 assert(SCIPconsIsTransformed(cons));
3584
3585 if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3586 {
3587 SCIP_VAR** vars;
3588 SCIP_Real* vals;
3589 int v;
3590
3591 /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3592 vars = consdata->vars;
3593 vals = consdata->vals;
3594
3595 for( v = 0; v < consdata->nvars; ++v )
3596 {
3597 assert(vars[v] != NULL);
3598 assert(!SCIPisZero(scip, vals[v]));
3599
3600 if( SCIPisPositive(scip, vals[v]) )
3601 {
3602 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3603 }
3604 else
3605 {
3606 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3607 }
3608 }
3609 }
3610 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3611 {
3612 SCIP_VAR** vars;
3613 SCIP_Real* vals;
3614 int v;
3615
3616 /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3617 vars = consdata->vars;
3618 vals = consdata->vals;
3619
3620 for( v = 0; v < consdata->nvars; ++v )
3621 {
3622 assert(vars[v] != NULL);
3623 assert(!SCIPisZero(scip, vals[v]));
3624
3625 if( SCIPisPositive(scip, vals[v]) )
3626 {
3627 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3628 }
3629 else
3630 {
3631 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3632 }
3633 }
3634 }
3635 }
3636
3637 /* 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 */
3638 if( !SCIPisInfinity(scip, ABS(rhs)) && SCIPisLT(scip, rhs, consdata->rhs) )
3639 {
3640 consdata->boundstightened = 0;
3641 consdata->presolved = FALSE;
3642 consdata->cliquesadded = FALSE;
3643 consdata->implsadded = FALSE;
3644
3645 /* mark the constraint for propagation */
3646 if( SCIPconsIsTransformed(cons) )
3647 {
3649 }
3650 }
3651
3652 /* set new right hand side and update constraint data */
3653 consdata->rhs = rhs;
3654 consdata->changed = TRUE;
3655 consdata->normalized = FALSE;
3656 consdata->upgradetried = FALSE;
3657 consdata->rangedrowpropagated = 0;
3658
3659 /* update the rhs of the LP row */
3660 if( consdata->row != NULL )
3661 {
3662 SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3663 }
3664
3665 return SCIP_OKAY;
3666}
3667
3668/** adds coefficient in linear constraint */
3669static
3671 SCIP* scip, /**< SCIP data structure */
3672 SCIP_CONS* cons, /**< linear constraint */
3673 SCIP_VAR* var, /**< variable of constraint entry */
3674 SCIP_Real val /**< coefficient of constraint entry */
3675 )
3676{
3677 SCIP_CONSDATA* consdata;
3678 SCIP_Bool transformed;
3679
3680 assert(scip != NULL);
3681 assert(cons != NULL);
3682 assert(var != NULL);
3683
3684 /* relaxation-only variables must not be used in checked or enforced constraints */
3685 assert(!SCIPvarIsRelaxationOnly(var) || (!SCIPconsIsChecked(cons) && !SCIPconsIsEnforced(cons)));
3686 consdata = SCIPconsGetData(cons);
3687 assert(consdata != NULL);
3688
3689 /* are we in the transformed problem? */
3690 transformed = SCIPconsIsTransformed(cons);
3691
3692 /* always use transformed variables in transformed constraints */
3693 if( transformed )
3694 {
3695 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3696 }
3697 assert(var != NULL);
3698 assert(transformed == SCIPvarIsTransformed(var));
3699
3700 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3701 consdata->vars[consdata->nvars] = var;
3702 consdata->vals[consdata->nvars] = val;
3703 consdata->nvars++;
3704
3705 /* capture variable */
3706 SCIP_CALL( SCIPcaptureVar(scip, var) );
3707
3708 /* if we are in transformed problem, the variable needs an additional event data */
3709 if( transformed )
3710 {
3711 if( consdata->eventdata != NULL )
3712 {
3713 SCIP_CONSHDLR* conshdlr;
3714 SCIP_CONSHDLRDATA* conshdlrdata;
3715
3716 /* check for event handler */
3717 conshdlr = SCIPconsGetHdlr(cons);
3718 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3719 assert(conshdlrdata != NULL);
3720 assert(conshdlrdata->eventhdlr != NULL);
3721
3722 /* initialize eventdata array */
3723 consdata->eventdata[consdata->nvars-1] = NULL;
3724
3725 /* catch bound change events of variable */
3726 SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3727 }
3728
3729 /* update minimum and maximum activities */
3730 if( !SCIPisZero(scip, val) )
3731 consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3732 }
3733
3734 /* install rounding locks for new variable with non-zero coefficient */
3735 if( !SCIPisZero(scip, val) )
3736 {
3737 SCIP_CALL( lockRounding(scip, cons, var, val) );
3738 }
3739
3740 /* mark the constraint for propagation */
3741 if( transformed )
3742 {
3744 }
3745
3746 consdata->boundstightened = 0;
3747 consdata->presolved = FALSE;
3748 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3749
3750 if( consdata->validsignature )
3751 consdataUpdateSignatures(consdata, consdata->nvars-1);
3752
3753 consdata->changed = TRUE;
3754 consdata->normalized = FALSE;
3755 consdata->upgradetried = FALSE;
3756 consdata->cliquesadded = FALSE;
3757 consdata->implsadded = FALSE;
3758 consdata->rangedrowpropagated = 0;
3759 consdata->merged = FALSE;
3760
3761 if( consdata->nvars == 1 )
3762 {
3763 consdata->indexsorted = TRUE;
3764 consdata->coefsorted = TRUE;
3765 }
3766 else
3767 {
3769 {
3770 consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3771 consdata->coefsorted = FALSE;
3772 }
3773 else
3774 {
3775 consdata->indexsorted = FALSE;
3776 consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3777 }
3778 }
3779
3780 /* update hascontvar and hasnonbinvar flags */
3781 if( consdata->hasnonbinvalid && !consdata->hascontvar )
3782 {
3783 SCIP_VARTYPE vartype = SCIPvarGetType(var);
3784
3785 if( vartype != SCIP_VARTYPE_BINARY )
3786 {
3787 consdata->hasnonbinvar = TRUE;
3788
3789 if( vartype == SCIP_VARTYPE_CONTINUOUS )
3790 consdata->hascontvar = TRUE;
3791 }
3792 }
3793
3794 /* add the new coefficient to the LP row */
3795 if( consdata->row != NULL )
3796 {
3797 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3798 }
3799
3800 return SCIP_OKAY;
3801}
3802
3803/** deletes coefficient at given position from linear constraint data */
3804static
3806 SCIP* scip, /**< SCIP data structure */
3807 SCIP_CONS* cons, /**< linear constraint */
3808 int pos /**< position of coefficient to delete */
3809 )
3810{
3811 SCIP_CONSDATA* consdata;
3812 SCIP_VAR* var;
3813 SCIP_Real val;
3814
3815 assert(scip != NULL);
3816 assert(cons != NULL);
3817
3818 consdata = SCIPconsGetData(cons);
3819 assert(consdata != NULL);
3820 assert(0 <= pos && pos < consdata->nvars);
3821
3822 var = consdata->vars[pos];
3823 val = consdata->vals[pos];
3824 assert(var != NULL);
3825
3826 /* remove rounding locks for deleted variable with non-zero coefficient */
3827 if( !SCIPisZero(scip, val) )
3828 {
3829 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3830 }
3831
3832 /* if we are in transformed problem, delete the event data of the variable */
3833 if( SCIPconsIsTransformed(cons) )
3834 {
3835 SCIP_CONSHDLR* conshdlr;
3836 SCIP_CONSHDLRDATA* conshdlrdata;
3837
3838 /* check for event handler */
3839 conshdlr = SCIPconsGetHdlr(cons);
3840 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3841 assert(conshdlrdata != NULL);
3842 assert(conshdlrdata->eventhdlr != NULL);
3843
3844 /* drop bound change events of variable */
3845 if( consdata->eventdata != NULL )
3846 {
3847 SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3848 assert(consdata->eventdata[pos] == NULL);
3849 }
3850 }
3851
3852 /* move the last variable to the free slot */
3853 if( pos != consdata->nvars - 1 )
3854 {
3855 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3856 consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3857
3858 if( consdata->eventdata != NULL )
3859 {
3860 consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3861 assert(consdata->eventdata[pos] != NULL);
3862 consdata->eventdata[pos]->varpos = pos;
3863 }
3864
3865 consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3866 consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3867 }
3868 consdata->nvars--;
3869
3870 /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3871 * of the remaining variable, or give exactly 0.0)
3872 */
3873 if( consdata->nvars <= 1 )
3875 else
3876 {
3877 /* if we are in transformed problem, update minimum and maximum activities */
3878 if( SCIPconsIsTransformed(cons) && !SCIPisZero(scip, val) )
3879 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3880 }
3881
3882 /* mark the constraint for propagation */
3883 if( SCIPconsIsTransformed(cons) )
3884 {
3886 }
3887
3888 consdata->boundstightened = 0;
3889 consdata->presolved = FALSE;
3890 consdata->validsignature = FALSE;
3891 consdata->changed = TRUE;
3892 consdata->normalized = FALSE;
3893 consdata->upgradetried = FALSE;
3894 consdata->cliquesadded = FALSE;
3895 consdata->implsadded = FALSE;
3896 consdata->rangedrowpropagated = 0;
3897
3898 /* check if hasnonbinvar flag might be incorrect now */
3899 if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3900 {
3901 consdata->hasnonbinvalid = FALSE;
3902 }
3903
3904 /* delete coefficient from the LP row */
3905 if( consdata->row != NULL )
3906 {
3907 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3908 }
3909
3910 /* release variable */
3911 SCIP_CALL( SCIPreleaseVar(scip, &var) );
3912
3913 return SCIP_OKAY;
3914}
3915
3916/** changes coefficient value at given position of linear constraint data */
3917static
3919 SCIP* scip, /**< SCIP data structure */
3920 SCIP_CONS* cons, /**< linear constraint */
3921 int pos, /**< position of coefficient to delete */
3922 SCIP_Real newval /**< new value of coefficient */
3923 )
3924{
3925 SCIP_CONSDATA* consdata;
3926 SCIP_VAR* var;
3927 SCIP_Real val;
3928 SCIP_Bool locked;
3929 int i;
3930
3931 assert(scip != NULL);
3932 assert(cons != NULL);
3933 consdata = SCIPconsGetData(cons);
3934 assert(consdata != NULL);
3935 assert(0 <= pos && pos < consdata->nvars);
3936 var = consdata->vars[pos];
3937 assert(var != NULL);
3938 assert(SCIPvarIsTransformed(var) == SCIPconsIsTransformed(cons));
3939 val = consdata->vals[pos];
3940 assert(!SCIPisZero(scip, val) || !SCIPisZero(scip, newval));
3941
3942 locked = FALSE;
3943 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3944 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3945
3946 /* if necessary, update the rounding locks of the variable */
3947 if( locked && ( !SCIPisNegative(scip, val) || !SCIPisNegative(scip, newval) )
3948 && ( !SCIPisPositive(scip, val) || !SCIPisPositive(scip, newval) ) )
3949 {
3950 assert(SCIPconsIsTransformed(cons));
3951
3952 /* remove rounding locks for variable with old non-zero coefficient */
3953 if( !SCIPisZero(scip, val) )
3954 {
3955 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3956 }
3957
3958 /* install rounding locks for variable with new non-zero coefficient */
3959 if( !SCIPisZero(scip, newval) )
3960 {
3961 SCIP_CALL( lockRounding(scip, cons, var, newval) );
3962 }
3963 }
3964
3965 /* change the value */
3966 consdata->vals[pos] = newval;
3967
3968 if( consdata->coefsorted )
3969 {
3970 if( pos > 0 )
3971 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
3972 if( consdata->coefsorted && pos < consdata->nvars - 1 )
3973 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
3974 }
3975
3976 /* update minimum and maximum activities */
3977 if( SCIPconsIsTransformed(cons) )
3978 {
3979 if( SCIPisZero(scip, val) )
3980 consdataUpdateAddCoef(scip, consdata, var, newval, TRUE);
3981 else if( SCIPisZero(scip, newval) )
3982 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3983 else
3984 consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
3985 }
3986
3987 /* mark the constraint for propagation */
3988 if( SCIPconsIsTransformed(cons) )
3989 {
3991 }
3992
3993 consdata->boundstightened = 0;
3994 consdata->presolved = FALSE;
3995 consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
3996 consdata->changed = TRUE;
3997 consdata->normalized = FALSE;
3998 consdata->upgradetried = FALSE;
3999 consdata->cliquesadded = FALSE;
4000 consdata->implsadded = FALSE;
4001 consdata->rangedrowpropagated = 0;
4002
4003 return SCIP_OKAY;
4004}
4005
4006/** scales a linear constraint with a constant scalar */
4007static
4009 SCIP* scip, /**< SCIP data structure */
4010 SCIP_CONS* cons, /**< linear constraint to scale */
4011 SCIP_Real scalar /**< value to scale constraint with */
4012 )
4013{
4014 SCIP_CONSDATA* consdata;
4015 SCIP_Real newval;
4016 SCIP_Real absscalar;
4017 int i;
4018
4019 assert(scip != NULL);
4020 assert(cons != NULL);
4021
4022 consdata = SCIPconsGetData(cons);
4023 assert(consdata != NULL);
4024 assert(consdata->row == NULL);
4025 assert(scalar != 1.0);
4026
4027 if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4028 || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4029 {
4030 SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4031 SCIPconsGetName(cons), scalar);
4032
4033 return SCIP_OKAY;
4034 }
4035
4036 /* scale the coefficients */
4037 for( i = consdata->nvars - 1; i >= 0; --i )
4038 {
4039 newval = scalar * consdata->vals[i];
4040
4041 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4042 * flooring down our new value
4043 */
4044 if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4045 newval = SCIPfeasFloor(scip, newval + 0.5);
4046
4047 if( SCIPisZero(scip, newval) )
4048 {
4049 SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4050 consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4051 SCIP_CALL( delCoefPos(scip, cons, i) );
4052 }
4053 else
4054 consdata->vals[i] = newval;
4055 }
4056
4057 /* scale the sides */
4058 if( scalar < 0.0 )
4059 {
4060 SCIP_Real lhs;
4061
4062 lhs = consdata->lhs;
4063 consdata->lhs = -consdata->rhs;
4064 consdata->rhs = -lhs;
4065 }
4066 absscalar = REALABS(scalar);
4067 if( !SCIPisInfinity(scip, -consdata->lhs) )
4068 {
4069 newval = absscalar * consdata->lhs;
4070
4071 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4072 * flooring down our new value
4073 */
4074 if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4075 consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4076 else
4077 consdata->lhs = newval;
4078 }
4079 if( !SCIPisInfinity(scip, consdata->rhs) )
4080 {
4081 newval = absscalar * consdata->rhs;
4082
4083 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4084 * our new value
4085 */
4086 if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4087 consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4088 else
4089 consdata->rhs = newval;
4090 }
4091
4093 consdata->cliquesadded = FALSE;
4094 consdata->implsadded = FALSE;
4095
4096 return SCIP_OKAY;
4097}
4098
4099/** perform deletion of variables in all constraints of the constraint handler */
4100static
4102 SCIP* scip, /**< SCIP data structure */
4103 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4104 SCIP_CONS** conss, /**< array of constraints */
4105 int nconss /**< number of constraints */
4106 )
4107{
4108 SCIP_CONSDATA* consdata;
4109 int i;
4110 int v;
4111
4112 assert(scip != NULL);
4113 assert(conshdlr != NULL);
4114 assert(conss != NULL);
4115 assert(nconss >= 0);
4116 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4117
4118 /* iterate over all constraints */
4119 for( i = 0; i < nconss; i++ )
4120 {
4121 consdata = SCIPconsGetData(conss[i]);
4122
4123 /* constraint is marked, that some of its variables were deleted */
4124 if( consdata->varsdeleted )
4125 {
4126 /* iterate over all variables of the constraint and delete them from the constraint */
4127 for( v = consdata->nvars - 1; v >= 0; --v )
4128 {
4129 if( SCIPvarIsDeleted(consdata->vars[v]) )
4130 {
4131 SCIP_CALL( delCoefPos(scip, conss[i], v) );
4132 }
4133 }
4134 consdata->varsdeleted = FALSE;
4135 }
4136 }
4137
4138 return SCIP_OKAY;
4139}
4140
4141
4142/** normalizes a linear constraint with the following rules:
4143 * - if all coefficients have them same absolute value, change them to (-)1.0
4144 * - multiplication with +1 or -1:
4145 * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4146 * if the current rule doesn't determine the sign):
4147 * 1. the right hand side must not be negative
4148 * 2. the right hand side must not be infinite
4149 * 3. the absolute value of the right hand side must be greater than that of the left hand side
4150 * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4151 * 5. multiply with +1
4152 * - rationals to integrals
4153 * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4154 * by the smallest common multiple of all denominators to get integral coefficients.
4155 * Forbid large denominators due to numerical stability.
4156 * - division by greatest common divisor
4157 * If all coefficients are integral, divide them by the greatest common divisor.
4158 */
4159static
4161 SCIP* scip, /**< SCIP data structure */
4162 SCIP_CONS* cons, /**< linear constraint to normalize */
4163 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4164 )
4165{
4166 SCIP_CONSDATA* consdata;
4167 SCIP_Real* vals;
4168 SCIP_Longint scm;
4169 SCIP_Longint nominator;
4170 SCIP_Longint denominator;
4171 SCIP_Longint gcd;
4172 SCIP_Longint maxmult;
4173 SCIP_Real epsilon;
4174 SCIP_Real feastol;
4175 SCIP_Real maxabsval;
4176 SCIP_Real minabsval;
4177 SCIP_Bool success;
4178 SCIP_Bool onlyintegral;
4179 int nvars;
4180 int mult;
4181 int nposcoeffs;
4182 int nnegcoeffs;
4183 int i;
4184
4185 assert(scip != NULL);
4186 assert(cons != NULL);
4187 assert(infeasible != NULL);
4188
4189 *infeasible = FALSE;
4190
4191 /* we must not change a modifiable constraint in any way */
4192 if( SCIPconsIsModifiable(cons) )
4193 return SCIP_OKAY;
4194
4195 /* get constraint data */
4196 consdata = SCIPconsGetData(cons);
4197 assert(consdata != NULL);
4198
4199 /* check, if the constraint is already normalized */
4200 if( consdata->normalized )
4201 return SCIP_OKAY;
4202
4203 /* get coefficient arrays */
4204 vals = consdata->vals;
4205 nvars = consdata->nvars;
4206 assert(nvars == 0 || vals != NULL);
4207
4208 if( nvars == 0 )
4209 {
4210 consdata->normalized = TRUE;
4211 return SCIP_OKAY;
4212 }
4213
4214 assert(vals != NULL);
4215
4216 /* get maximum and minimum absolute coefficient */
4217 maxabsval = consdataGetMaxAbsval(consdata);
4218 minabsval = consdataGetMinAbsval(consdata);
4219
4220 /* return if scaling by maxval will eliminate coefficients */
4221 if( SCIPisZero(scip, minabsval/maxabsval) )
4222 return SCIP_OKAY;
4223
4224 /* return if scaling by maxval will eliminate or generate non-zero sides */
4225 if( !SCIPisInfinity(scip, consdata->lhs) && SCIPisFeasZero(scip, consdata->lhs) != SCIPisFeasZero(scip, consdata->lhs/maxabsval) )
4226 return SCIP_OKAY;
4227 if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasZero(scip, consdata->rhs) != SCIPisFeasZero(scip, consdata->rhs/maxabsval) )
4228 return SCIP_OKAY;
4229
4230 /* check if not all absolute coefficients are near 1.0 but scaling could do */
4231 if( SCIPisLT(scip, minabsval, 1.0) != SCIPisGT(scip, maxabsval, 1.0) )
4232 {
4233 SCIP_Real scalar;
4234
4235 /* calculate scale of the average minimum and maximum absolute coefficient to 1.0 */
4236 scalar = 2.0 / (minabsval + maxabsval);
4237
4238 /* check if all scaled absolute coefficients are near 1.0
4239 * we can relax EQ(x,1.0) to LE(x,1.0), as LT(x,1.0) is not possible
4240 */
4241 if( SCIPisLE(scip, scalar * maxabsval, 1.0) )
4242 {
4243 SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4245 SCIP_CALL( scaleCons(scip, cons, scalar) );
4246
4247 /* get new consdata information, because scaleCons() might have deleted variables */
4248 vals = consdata->vals;
4249 nvars = consdata->nvars;
4250
4251 assert(nvars == 0 || vals != NULL);
4252 }
4253 }
4254
4255 /* nvars might have changed */
4256 if( nvars == 0 )
4257 {
4258 consdata->normalized = TRUE;
4259 return SCIP_OKAY;
4260 }
4261
4262 assert(vals != NULL);
4263
4264 /* calculate the maximal multiplier for common divisor calculation:
4265 * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4266 * which means, a value of feastol/epsilon should be used as maximal multiplier;
4267 * additionally, we don't want to scale the constraint if this would lead to too
4268 * large coefficients
4269 */
4270 epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4271 feastol = SCIPfeastol(scip);
4272 maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4273
4274 if( !consdata->hasnonbinvalid )
4275 consdataCheckNonbinvar(consdata);
4276
4277 /* get maximum absolute coefficient */
4278 maxabsval = consdataGetMaxAbsval(consdata);
4279
4280 /* if all variables are of integral type we will allow a greater multiplier */
4281 if( !consdata->hascontvar )
4282 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4283 else
4284 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4285
4286 /*
4287 * multiplication with +1 or -1
4288 */
4289 mult = 0;
4290
4291 /* 1. the right hand side must not be negative */
4292 if( SCIPisPositive(scip, consdata->lhs) )
4293 mult = +1;
4294 else if( SCIPisNegative(scip, consdata->rhs) )
4295 mult = -1;
4296
4297 if( mult == 0 )
4298 {
4299 /* 2. the right hand side must not be infinite */
4300 if( SCIPisInfinity(scip, -consdata->lhs) )
4301 mult = +1;
4302 else if( SCIPisInfinity(scip, consdata->rhs) )
4303 mult = -1;
4304 }
4305
4306 if( mult == 0 )
4307 {
4308 /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4309 if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4310 mult = +1;
4311 else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4312 mult = -1;
4313 }
4314
4315 if( mult == 0 )
4316 {
4317 /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4318 nposcoeffs = 0;
4319 nnegcoeffs = 0;
4320 for( i = 0; i < nvars; ++i )
4321 {
4322 if( vals[i] > 0.0 )
4323 nposcoeffs++;
4324 else
4325 nnegcoeffs++;
4326 }
4327 if( nposcoeffs > nnegcoeffs )
4328 mult = +1;
4329 else if( nposcoeffs < nnegcoeffs )
4330 mult = -1;
4331 }
4332
4333 if( mult == 0 )
4334 {
4335 /* 5. multiply with +1 */
4336 mult = +1;
4337 }
4338
4339 assert(mult == +1 || mult == -1);
4340 if( mult == -1 )
4341 {
4342 /* scale the constraint with -1 */
4343 SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4345 SCIP_CALL( scaleCons(scip, cons, -1.0) );
4346
4347 /* scalecons() can delete variables, but scaling with -1 should not do that */
4348 assert(nvars == consdata->nvars);
4349 }
4350
4351 /*
4352 * rationals to integrals
4353 *
4354 * @todo try scaling only on behalf of non-continuous variables
4355 */
4356 success = TRUE;
4357 scm = 1;
4358 for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4359 {
4360 if( !SCIPisIntegral(scip, vals[i]) )
4361 {
4362 /* epsilon has been slightly decreased above - to be on the safe side */
4363 success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4364 if( success )
4365 scm = SCIPcalcSmaComMul(scm, denominator);
4366 }
4367 }
4368 assert(scm >= 1);
4369
4370 /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4371 * their greatest common divisor
4372 */
4373 onlyintegral = TRUE;
4374 if( scm == 1 )
4375 {
4376 for( i = nvars - 1; i >= 0; --i )
4377 {
4378 if( !SCIPisIntegral(scip, vals[i]) )
4379 {
4380 onlyintegral = FALSE;
4381 break;
4382 }
4383 }
4384 }
4385
4386 success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4387 if( success && scm != 1 )
4388 {
4389 /* scale the constraint with the smallest common multiple of all denominators */
4390 SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4392 SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4393
4394 if( consdata->validmaxabsval )
4395 {
4396 consdata->maxabsval *= REALABS((SCIP_Real)scm);
4397 if( !SCIPisIntegral(scip, consdata->maxabsval) )
4398 {
4399 consdata->validmaxabsval = FALSE;
4400 consdata->maxabsval = SCIP_INVALID;
4401 consdataCalcMaxAbsval(consdata);
4402 }
4403 }
4404
4405 if( consdata->validminabsval )
4406 {
4407 consdata->minabsval *= REALABS((SCIP_Real)scm);
4408 if( !SCIPisIntegral(scip, consdata->minabsval) )
4409 {
4410 consdata->validminabsval = FALSE;
4411 consdata->minabsval = SCIP_INVALID;
4412 consdataCalcMinAbsval(consdata);
4413 }
4414 }
4415
4416 /* get new consdata information, because scalecons() might have deleted variables */
4417 vals = consdata->vals;
4418 nvars = consdata->nvars;
4419 assert(nvars == 0 || vals != NULL);
4420 }
4421
4422 /*
4423 * division by greatest common divisor
4424 */
4425 if( success && nvars >= 1 )
4426 {
4427 /* all coefficients are integral: divide them by their greatest common divisor */
4428 assert(SCIPisIntegral(scip, vals[0]));
4429
4430 gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4431 for( i = 1; i < nvars && gcd > 1; ++i )
4432 {
4433 assert(SCIPisIntegral(scip, vals[i]));
4434 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4435 }
4436
4437 if( gcd > 1 )
4438 {
4439 /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4440 if( !consdata->hascontvar && onlyintegral )
4441 {
4442 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4443 {
4444 *infeasible = TRUE;
4445
4446 SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4448
4449 return SCIP_OKAY;
4450 }
4451 }
4452
4453 /* divide the constraint by the greatest common divisor of the coefficients */
4454 SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4456 SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4457
4458 if( consdata->validmaxabsval )
4459 {
4460 consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4461 }
4462 if( consdata->validminabsval )
4463 {
4464 consdata->minabsval /= REALABS((SCIP_Real)gcd);
4465 }
4466 }
4467 }
4468
4469 /* mark constraint to be normalized */
4470 consdata->normalized = TRUE;
4471
4472 SCIPdebugMsg(scip, "normalized constraint:\n");
4474
4475 return SCIP_OKAY;
4476}
4477
4478/** replaces multiple occurrences of a variable by a single non-zero coefficient */
4479static
4481 SCIP* scip, /**< SCIP data structure */
4482 SCIP_CONS* cons /**< linear constraint */
4483 )
4484{
4485 SCIP_CONSDATA* consdata;
4486 SCIP_VAR* var;
4487 SCIP_Real valsum;
4488 int v;
4489
4490 assert(scip != NULL);
4491 assert(cons != NULL);
4492
4493 consdata = SCIPconsGetData(cons);
4494 assert(consdata != NULL);
4495
4496 if( consdata->merged )
4497 return SCIP_OKAY;
4498
4499 /* sort the constraint */
4500 SCIP_CALL( consdataSort(scip, consdata) );
4501
4502 v = consdata->nvars - 1;
4503
4504 /* go backwards through the constraint looking for multiple occurrences of the same variable;
4505 * backward direction is necessary, since delCoefPos() modifies the given position and
4506 * the subsequent ones
4507 */
4508 while( v >= 0 )
4509 {
4510 var = consdata->vars[v];
4511 valsum = consdata->vals[v];
4512
4513 /* sum multiple occurrences */
4514 while( v >= 1 && consdata->vars[v-1] == var )
4515 {
4516 SCIP_CALL( delCoefPos(scip, cons, v) );
4517 --v;
4518 valsum += consdata->vals[v];
4519 }
4520
4521 assert(consdata->vars[v] == var);
4522
4523 /* modify the last existing occurrence of the variable */
4524 if( SCIPisZero(scip, valsum) )
4525 {
4526 SCIP_CALL( delCoefPos(scip, cons, v) );
4527 }
4528 else if( valsum != consdata->vals[v] ) /*lint !e777*/
4529 {
4530 SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4531 }
4532
4533 --v;
4534 }
4535
4536 consdata->merged = TRUE;
4537
4538 return SCIP_OKAY;
4539}
4540
4541/** replaces all fixed and aggregated variables by their non-fixed counterparts */
4542static
4544 SCIP* scip, /**< SCIP data structure */
4545 SCIP_CONS* cons, /**< linear constraint */
4546 SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4547 * information is not needed; in this case, we apply all fixings
4548 * instead of stopping after the first infeasible one */
4549 )
4550{
4551 SCIP_CONSDATA* consdata;
4552 int v;
4553
4554 assert(scip != NULL);
4555 assert(cons != NULL);
4556
4557 if( infeasible != NULL )
4558 *infeasible = FALSE;
4559
4560 consdata = SCIPconsGetData(cons);
4561 assert(consdata != NULL);
4562
4563 if( consdata->eventdata == NULL )
4564 {
4565 SCIP_CONSHDLR* conshdlr;
4566 SCIP_CONSHDLRDATA* conshdlrdata;
4567
4568 conshdlr = SCIPconsGetHdlr(cons);
4569 assert(conshdlr != NULL);
4570
4571 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4572 assert(conshdlrdata != NULL);
4573
4574 /* catch bound change events of variables */
4575 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4576 assert(consdata->eventdata != NULL);
4577 }
4578
4579 if( !consdata->removedfixings )
4580 {
4581 SCIP_Real lhssubtrahend;
4582 SCIP_Real rhssubtrahend;
4583
4584 /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4585 * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4586 */
4587 assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4588
4589 lhssubtrahend = 0.0;
4590 rhssubtrahend = 0.0;
4591
4592 SCIPdebugMsg(scip, "applying fixings:\n");
4594
4595 v = 0;
4596 while( v < consdata->nvars )
4597 {
4598 SCIP_VAR* var = consdata->vars[v];
4599 SCIP_Real scalar = consdata->vals[v];
4600 SCIP_Real constant = 0.0;
4601 assert(SCIPvarIsTransformed(var));
4602
4603 SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
4604
4605 switch( SCIPvarGetStatus(var) )
4606 {
4608 SCIPerrorMessage("original variable in transformed linear constraint\n");
4609 return SCIP_INVALIDDATA;
4610
4613 SCIPerrorMessage("aggregated variable after resolving linear term\n");
4614 return SCIP_INVALIDDATA;
4615
4618 if( var != consdata->vars[v] )
4619 {
4620 assert(scalar != 0.0);
4621 SCIP_CALL( addCoef(scip, cons, var, scalar) );
4622 SCIP_CALL( delCoefPos(scip, cons, v) );
4623
4624 assert(!SCIPisInfinity(scip, ABS(constant)));
4625 if( !SCIPisInfinity(scip, -consdata->lhs) )
4626 lhssubtrahend += constant;
4627 if( !SCIPisInfinity(scip, consdata->rhs) )
4628 rhssubtrahend += constant;
4629 }
4630 ++v;
4631 break;
4632
4634 if( scalar != 0.0 )
4635 {
4636 SCIP_VAR** aggrvars;
4637 SCIP_Real* aggrscalars;
4638 SCIP_Real aggrconstant;
4639 int naggrvars;
4640 int i;
4641
4643 aggrvars = SCIPvarGetMultaggrVars(var);
4644 aggrscalars = SCIPvarGetMultaggrScalars(var);
4645 aggrconstant = SCIPvarGetMultaggrConstant(var);
4646 naggrvars = SCIPvarGetMultaggrNVars(var);
4647
4648 for( i = 0; i < naggrvars; ++i )
4649 {
4650 SCIP_CALL( addCoef(scip, cons, aggrvars[i], scalar * aggrscalars[i]) );
4651 }
4652
4653 constant += scalar * aggrconstant;
4654 }
4655 /*lint -fallthrough*/
4656
4658 if( !SCIPisInfinity(scip, -consdata->lhs) )
4659 {
4660 if( SCIPisInfinity(scip, ABS(constant)) )
4661 {
4662 /* if lhs gets infinity it means that the problem is infeasible */
4663 if( constant < 0.0 )
4664 {
4666
4667 if( infeasible != NULL )
4668 {
4669 *infeasible = TRUE;
4670 return SCIP_OKAY;
4671 }
4672 }
4673 else
4674 {
4675 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4676 }
4677 }
4678 else
4679 lhssubtrahend += constant;
4680 }
4681 if( !SCIPisInfinity(scip, consdata->rhs) )
4682 {
4683 if( SCIPisInfinity(scip, ABS(constant)) )
4684 {
4685 /* if rhs gets -infinity it means that the problem is infeasible */
4686 if( constant > 0.0 )
4687 {
4688 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4689
4690 if( infeasible != NULL )
4691 {
4692 *infeasible = TRUE;
4693 return SCIP_OKAY;
4694 }
4695 }
4696 else
4697 {
4699 }
4700 }
4701 else
4702 rhssubtrahend += constant;
4703 }
4704 SCIP_CALL( delCoefPos(scip, cons, v) );
4705 break;
4706
4707 default:
4708 SCIPerrorMessage("unknown variable status\n");
4709 SCIPABORT();
4710 return SCIP_INVALIDDATA; /*lint !e527*/
4711 }
4712 }
4713
4714 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4715 {
4716 /* check left hand side of unmodifiable empty constraint with former feasibility tolerance */
4717 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4718 {
4719 if( SCIPisFeasLT(scip, lhssubtrahend, consdata->lhs) )
4720 {
4722
4723 if( infeasible != NULL )
4724 {
4725 *infeasible = TRUE;
4726 return SCIP_OKAY;
4727 }
4728 }
4729 else
4730 {
4731 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4732 }
4733 }
4734 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
4735 * causing wrong fixings of other variables --> better use a real zero here
4736 */
4737 else if( SCIPisGE(scip, ABS(consdata->lhs), 1.0) && SCIPisEQ(scip, lhssubtrahend, consdata->lhs) )
4738 {
4739 SCIP_CALL( chgLhs(scip, cons, 0.0) );
4740 }
4741 else
4742 {
4743 SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4744 }
4745 }
4746 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs) )
4747 {
4748 /* check right hand side of unmodifiable empty constraint with former feasibility tolerance */
4749 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4750 {
4751 if( SCIPisFeasGT(scip, rhssubtrahend, consdata->rhs) )
4752 {
4753 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4754
4755 if( infeasible != NULL )
4756 {
4757 *infeasible = TRUE;
4758 return SCIP_OKAY;
4759 }
4760 }
4761 else
4762 {
4764 }
4765 }
4766 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
4767 * causing wrong fixings of other variables --> better use a real zero here
4768 */
4769 else if( SCIPisGE(scip, ABS(consdata->rhs), 1.0) && SCIPisEQ(scip, rhssubtrahend, consdata->rhs) )
4770 {
4771 SCIP_CALL( chgRhs(scip, cons, 0.0) );
4772 }
4773 else
4774 {
4775 SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4776 }
4777 }
4778 consdata->removedfixings = TRUE;
4779
4780 SCIPdebugMsg(scip, "after fixings:\n");
4782
4783 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4784 * to clean up the constraint
4785 */
4786 SCIP_CALL( mergeMultiples(scip, cons) );
4787
4788 SCIPdebugMsg(scip, "after merging:\n");
4790 }
4791 assert(consdata->removedfixings);
4792
4793#ifndef NDEBUG
4794 /* check, if all fixings are applied */
4795 for( v = 0; v < consdata->nvars; ++v )
4796 assert(SCIPvarIsActive(consdata->vars[v]));
4797#endif
4798
4799 return SCIP_OKAY;
4800}
4801
4802/** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4803 * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4804 * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4805 * conflict detecting constraint by using NULL as inferred variable
4806 */
4807static
4809 SCIP* scip, /**< SCIP data structure */
4810 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4811 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4812 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4813 int inferpos, /**< position of the inferred variable in the vars array */
4814 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4815 )
4816{
4817 SCIP_CONSDATA* consdata;
4818 SCIP_VAR** vars;
4819 SCIP_Real* vals;
4820 int nvars;
4821 int i;
4822
4823 assert(scip != NULL);
4824 assert(cons != NULL);
4825
4826 consdata = SCIPconsGetData(cons);
4827
4828 assert(consdata != NULL);
4829
4830 vars = consdata->vars;
4831 vals = consdata->vals;
4832 nvars = consdata->nvars;
4833
4834 assert(vars != NULL || nvars == 0);
4835 assert(vals != NULL || nvars == 0);
4836
4837 assert(-1 <= inferpos && inferpos < nvars);
4838 assert((infervar == NULL) == (inferpos == -1));
4839 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4840
4841 /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4842 * residual value, depending on whether the left or right hand side is responsible for the bound change:
4843 * - if the right hand side is the reason, the minimal residual activity is responsible
4844 * - if the left hand side is the reason, the maximal residual activity is responsible
4845 */
4846
4847 /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4848 if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4849 {
4850 SCIP_Real minresactivity;
4851 SCIP_Real maxresactivity;
4852 SCIP_Bool ismintight;
4853 SCIP_Bool ismaxtight;
4854 SCIP_Bool isminsettoinfinity;
4855 SCIP_Bool ismaxsettoinfinity;
4856
4857 minresactivity = -SCIPinfinity(scip);
4858 maxresactivity = SCIPinfinity(scip);
4859
4860 /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4861 if( infervar != NULL )
4862 {
4863 assert(vals != NULL); /* for flexelint */
4864 if( reasonisrhs )
4865 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4866 &ismintight, NULL, &isminsettoinfinity, NULL);
4867 else
4868 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4869 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4870 }
4871 else
4872 {
4873 if( reasonisrhs )
4874 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4875 &ismintight, NULL, &isminsettoinfinity, NULL);
4876 else
4877 consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4878 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4879 }
4880
4881 /* we can only do something clever, if the residual activity is finite and not relaxed */
4882 if( (reasonisrhs && !isminsettoinfinity && ismintight) || (!reasonisrhs && !ismaxsettoinfinity && ismaxtight) ) /*lint !e644*/
4883 {
4884 SCIP_Real rescap;
4885 SCIP_Bool resactisinf;
4886
4887 resactisinf = FALSE;
4888
4889 /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4890 * than its inferred bound
4891 */
4892 if( infervar != NULL )
4893 {
4894 assert(vals != NULL); /* for flexelint */
4895
4896 if( reasonisrhs )
4897 {
4898 if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4899 {
4900 consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4901 if( SCIPisInfinity(scip, -minresactivity) )
4902 resactisinf = TRUE;
4903 }
4904 rescap = consdata->rhs - minresactivity;
4905 }
4906 else
4907 {
4908 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4909 {
4910 consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4911 if( SCIPisInfinity(scip, maxresactivity) )
4912 resactisinf = TRUE;
4913 }
4914 rescap = consdata->lhs - maxresactivity;
4915 }
4916
4917 if( reasonisrhs == (vals[inferpos] > 0.0) )
4918 rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4919 else
4920 rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
4921 }
4922 else
4923 rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4924
4925 if( !resactisinf )
4926 {
4927 /* now add bounds as reasons until the residual capacity is exceeded */
4928 for( i = 0; i < nvars; ++i )
4929 {
4930 assert( vars != NULL && vals != NULL ); /* for lint */
4931
4932 /* zero coefficients and the inferred variable can be ignored */
4933 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4934 continue;
4935
4936 /* check if the residual capacity is exceeded */
4937 if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4938 || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4939 break;
4940
4941 /* update the residual capacity due to the local bound of this variable */
4942 if( reasonisrhs == (vals[i] > 0.0) )
4943 {
4944 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4945 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4946 rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4947 }
4948 else
4949 {
4950 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4951 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4952 rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4953 }
4954 }
4955 return SCIP_OKAY;
4956 }
4957 }
4958 }
4959
4960 /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4961 for( i = 0; i < nvars; ++i )
4962 {
4963 assert(vars != NULL); /* for flexelint */
4964 assert(vals != NULL); /* for flexelint */
4965
4966 /* zero coefficients and the inferred variable can be ignored */
4967 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4968 continue;
4969
4970 if( reasonisrhs == (vals[i] > 0.0) )
4971 {
4972 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4973 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4974 }
4975 else
4976 {
4977 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
4978 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4979 }
4980 }
4981
4982 return SCIP_OKAY;
4983}
4984
4985/** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
4986 * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
4987 * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
4988 */
4989static
4991 SCIP* scip, /**< SCIP data structure */
4992 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4993 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4994 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4995 int inferpos /**< position of the inferred variable in the vars array, or -1 */
4996 )
4997{
4998 SCIP_CONSDATA* consdata;
4999 SCIP_VAR** vars;
5000 int nvars;
5001 int v;
5002
5003 assert(scip != NULL);
5004 assert(cons != NULL);
5005
5006 consdata = SCIPconsGetData(cons);
5007 assert(consdata != NULL);
5008 vars = consdata->vars;
5009 nvars = consdata->nvars;
5010 assert(vars != NULL || nvars == 0);
5011 assert(-1 <= inferpos && inferpos < nvars);
5012 assert((infervar == NULL) == (inferpos == -1));
5013 assert(inferpos == -1 || vars != NULL);
5014 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5015
5016 /* collect all fixed variables */
5017 for( v = nvars - 1; v >= 0; --v )
5018 {
5019 assert(vars != NULL); /* for flexelint */
5020
5021 /* need to add old bounds before propagation of inferrence variable */
5022 if( vars[v] == infervar )
5023 {
5024 assert(vars[v] != NULL);
5025
5026 if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5027 {
5028 /* @todo get boundchange index before this last boundchange and correct the index */
5029 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5030 }
5031
5032 if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5033 {
5034 /* @todo get boundchange index before this last boundchange and correct the index */
5035 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5036 }
5037
5038 continue;
5039 }
5040
5041 /* check for fixed variables */
5042 if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5043 {
5044 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5045 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5046 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5047 }
5048 }
5049
5050 return SCIP_OKAY;
5051}
5052
5053/** add reasoning variables to conflict candidate queue which led to the conflict */
5054static
5056 SCIP* scip, /**< SCIP data structure */
5057 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5058 int nvars, /**< number of variables reasoning the infeasibility */
5059 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5060 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5061 )
5062{
5063 int v;
5064
5065 assert(scip != NULL);
5066
5067 /* collect all variables for which the local bounds differ from their global bounds */
5068 for( v = nvars - 1; v >= 0; --v )
5069 {
5070 assert(vars != NULL);
5071
5072 /* check for local bound changes variables */
5073 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5074 {
5075 /* add conflict bound */
5076 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5077 }
5078
5079 if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5080 {
5081 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5082 }
5083 }
5084
5085 if( var != NULL )
5086 {
5087 if( bound < SCIPvarGetLbLocal(var) )
5088 {
5089 SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5090 }
5091
5092 if( bound > SCIPvarGetUbLocal(var) )
5093 {
5094 SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5095 }
5096 }
5097
5098 return SCIP_OKAY;
5099}
5100
5101/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5102 * propagation rule (see propagateCons()):
5103 * (1) activity residuals of all other variables tighten bounds of single variable
5104 */
5105static
5107 SCIP* scip, /**< SCIP data structure */
5108 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5109 SCIP_VAR* infervar, /**< variable that was deduced */
5110 INFERINFO inferinfo, /**< inference information */
5111 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5112 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5113 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5114 )
5115{
5116 SCIP_CONSDATA* consdata;
5117 SCIP_VAR** vars;
5118#ifndef NDEBUG
5119 SCIP_Real* vals;
5120#endif
5121 int nvars;
5122 int inferpos;
5123
5124 assert(scip != NULL);
5125 assert(cons != NULL);
5126 assert(result != NULL);
5127
5128 consdata = SCIPconsGetData(cons);
5129 assert(consdata != NULL);
5130 vars = consdata->vars;
5131 nvars = consdata->nvars;
5132#ifndef NDEBUG
5133 vals = consdata->vals;
5134 assert(vars != NULL);
5135 assert(vals != NULL);
5136#endif
5137
5138 /* get the position of the inferred variable in the vars array */
5139 inferpos = inferInfoGetPos(inferinfo);
5140 if( inferpos >= nvars || vars[inferpos] != infervar )
5141 {
5142 /* find inference variable in constraint */
5143 /**@todo use a binary search here; the variables can be sorted by variable index */
5144 for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5145 {}
5146 }
5147 assert(inferpos < nvars);
5148 assert(vars[inferpos] == infervar);
5149 assert(!SCIPisZero(scip, vals[inferpos]));
5150
5151 switch( inferInfoGetProprule(inferinfo) )
5152 {
5153 case PROPRULE_1_RHS:
5154 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5155 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5156 * domain in order to not exceed the right hand side of the inequality
5157 */
5158 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5159 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5160 *result = SCIP_SUCCESS;
5161 break;
5162
5163 case PROPRULE_1_LHS:
5164 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5165 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5166 * domain in order to not fall below the left hand side of the inequality
5167 */
5168 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5169 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5170 *result = SCIP_SUCCESS;
5171 break;
5172
5174 /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5175 * the given inference variable to their bounds in this given ranged row
5176 */
5177
5178 /* check that we really have a ranged row here */
5179 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5180 SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5181 *result = SCIP_SUCCESS;
5182 break;
5183
5184 case PROPRULE_INVALID:
5185 default:
5186 SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5187 inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5188 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5189 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5190 SCIPinfoMessage(scip, NULL, ";\n");
5191 return SCIP_INVALIDDATA;
5192 }
5193
5194 return SCIP_OKAY;
5195}
5196
5197/** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5198static
5200 SCIP* scip, /**< SCIP data structure */
5201 SCIP_CONS* cons, /**< conflict detecting constraint */
5202 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5203 )
5204{
5205 /* conflict analysis can only be applied in solving stage and if it is turned on */
5207 return SCIP_OKAY;
5208
5209 /* initialize conflict analysis */
5211
5212 /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5213 SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5214
5215 /* analyze the conflict */
5217
5218 return SCIP_OKAY;
5219}
5220
5221/** check if there is any hope of tightening some bounds */
5222static
5224 SCIP_CONS* cons /**< linear constraint */
5225 )
5226{
5227 SCIP_CONSDATA* consdata;
5228 int infcountmin;
5229 int infcountmax;
5230
5231 consdata = SCIPconsGetData(cons);
5232 assert(consdata != NULL);
5233
5234 infcountmin = consdata->minactivityneginf
5235 + consdata->minactivityposinf
5236 + consdata->minactivityneghuge
5237 + consdata->minactivityposhuge;
5238 infcountmax = consdata->maxactivityneginf
5239 + consdata->maxactivityposinf
5240 + consdata->maxactivityneghuge
5241 + consdata->maxactivityposhuge;
5242
5243 if( infcountmin > 1 && infcountmax > 1 )
5244 return FALSE;
5245
5246 return TRUE;
5247}
5248
5249/** tighten upper bound */
5250static
5252 SCIP* scip, /**< SCIP data structure */
5253 SCIP_CONS* cons, /**< linear constraint */
5254 int pos, /**< variable position */
5255 PROPRULE proprule, /**< propagation rule that deduced the value */
5256 SCIP_Real newub, /**< new upper bound */
5257 SCIP_Real oldub, /**< old upper bound */
5258 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5259 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5260 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5261 )
5262{
5263 SCIP_CONSDATA* consdata;
5264 SCIP_VAR* var;
5265 SCIP_Real lb;
5266 SCIP_Bool infeasible;
5267 SCIP_Bool tightened;
5268
5269 assert(cons != NULL);
5270 assert(!SCIPisInfinity(scip, newub));
5271
5272 consdata = SCIPconsGetData(cons);
5273 assert(consdata != NULL);
5274 var = consdata->vars[pos];
5275 assert(var != NULL);
5276
5277 lb = SCIPvarGetLbLocal(var);
5278 newub = SCIPadjustedVarUb(scip, var, newub);
5279
5280 if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5281 {
5282 SCIP_VARTYPE vartype;
5283
5284 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5285 SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5286 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5287
5288 vartype = SCIPvarGetType(var);
5289
5290 /* tighten upper bound */
5291 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5292
5293 if( infeasible )
5294 {
5295 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5296 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5297
5298 /* analyze conflict */
5300
5301 *cutoff = TRUE;
5302 }
5303 else if( tightened )
5304 {
5305 assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5306 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5307 SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5308
5309 (*nchgbds)++;
5310
5311 /* if variable type was changed we might be able to upgrade the constraint */
5312 if( vartype != SCIPvarGetType(var) )
5313 consdata->upgradetried = FALSE;
5314 }
5315 }
5316 return SCIP_OKAY;
5317}
5318
5319/** tighten lower bound */
5320static
5322 SCIP* scip, /**< SCIP data structure */
5323 SCIP_CONS* cons, /**< linear constraint */
5324 int pos, /**< variable position */
5325 PROPRULE proprule, /**< propagation rule that deduced the value */
5326 SCIP_Real newlb, /**< new lower bound */
5327 SCIP_Real oldlb, /**< old lower bound */
5328 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5329 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5330 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5331 )
5332{
5333 SCIP_CONSDATA* consdata;
5334 SCIP_VAR* var;
5335 SCIP_Real ub;
5336 SCIP_Bool infeasible;
5337 SCIP_Bool tightened;
5338
5339 assert(cons != NULL);
5340 assert(!SCIPisInfinity(scip, newlb));
5341
5342 consdata = SCIPconsGetData(cons);
5343 assert(consdata != NULL);
5344 var = consdata->vars[pos];
5345 assert(var != NULL);
5346
5347 ub = SCIPvarGetUbLocal(var);
5348 newlb = SCIPadjustedVarLb(scip, var, newlb);
5349
5350 if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5351 {
5352 SCIP_VARTYPE vartype;
5353
5354 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5355 SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5356 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5357
5358 vartype = SCIPvarGetType(var);
5359
5360 /* tighten lower bound */
5361 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5362
5363 if( infeasible )
5364 {
5365 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5366 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5367
5368 /* analyze conflict */
5370
5371 *cutoff = TRUE;
5372 }
5373 else if( tightened )
5374 {
5375 assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5376 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5377 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5378
5379 (*nchgbds)++;
5380
5381 /* if variable type was changed we might be able to upgrade the constraint */
5382 if( vartype != SCIPvarGetType(var) )
5383 consdata->upgradetried = FALSE;
5384 }
5385 }
5386 return SCIP_OKAY;
5387}
5388
5389/** tightens bounds of a single variable due to activity bounds (easy case) */
5390static
5392 SCIP* scip, /**< SCIP data structure */
5393 SCIP_CONS* cons, /**< linear constraint */
5394 int pos, /**< position of the variable in the vars array */
5395 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5396 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5397 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5398 )
5399{
5400 SCIP_CONSDATA* consdata;
5401 SCIP_VAR* var;
5402 SCIP_Real val;
5403 SCIP_Real lb;
5404 SCIP_Real ub;
5405 SCIP_Real lhs;
5406 SCIP_Real rhs;
5407
5408 assert(scip != NULL);
5409 assert(cons != NULL);
5410 assert(cutoff != NULL);
5411 assert(nchgbds != NULL);
5412
5413 /* we cannot tighten variables' bounds, if the constraint may be not complete */
5414 if( SCIPconsIsModifiable(cons) )
5415 return SCIP_OKAY;
5416
5417 consdata = SCIPconsGetData(cons);
5418 assert(consdata != NULL);
5419 assert(0 <= pos && pos < consdata->nvars);
5420
5421 *cutoff = FALSE;
5422
5423 var = consdata->vars[pos];
5424 assert(var != NULL);
5425
5426 /* we cannot tighten bounds of multi-aggregated variables */
5428 return SCIP_OKAY;
5429
5430 val = consdata->vals[pos];
5431 lhs = consdata->lhs;
5432 rhs = consdata->rhs;
5433 assert(!SCIPisZero(scip, val));
5434 assert(!SCIPisInfinity(scip, lhs));
5435 assert(!SCIPisInfinity(scip, -rhs));
5436
5437 lb = SCIPvarGetLbLocal(var);
5438 ub = SCIPvarGetUbLocal(var);
5439 assert(SCIPisLE(scip, lb, ub));
5440
5441 /* recompute activities if needed */
5442 if( !consdata->validactivities )
5443 consdataCalcActivities(scip, consdata);
5444 assert(consdata->validactivities);
5445 if( !consdata->validminact )
5447 assert(consdata->validminact);
5448
5449 if( val > 0.0 )
5450 {
5451 /* check, if we can tighten the variable's upper bound */
5452 if( !SCIPisInfinity(scip, rhs) )
5453 {
5454 SCIP_Real slack;
5455 SCIP_Real alpha;
5456
5457 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5458 assert(consdata->validminact);
5459
5460 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5461 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5462 {
5463 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5464 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5465
5466 *cutoff = TRUE;
5467 return SCIP_OKAY;
5468 }
5469
5470 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5471
5472 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5473 * it to zero
5474 */
5475 if( !SCIPisPositive(scip, slack) )
5476 slack = 0.0;
5477
5478 alpha = val * (ub - lb);
5479 assert(!SCIPisNegative(scip, alpha));
5480
5481 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5482 {
5483 SCIP_Real newub;
5484
5485 /* compute new upper bound */
5486 newub = lb + (slack / val);
5487
5488 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5489
5490 if( *cutoff )
5491 {
5492 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5493 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5494
5495 return SCIP_OKAY;
5496 }
5497
5498 /* collect the new upper bound which is needed for the lower bound computation */
5499 ub = SCIPvarGetUbLocal(var);
5500 }
5501 }
5502
5503 /* check, if we can tighten the variable's lower bound */
5504 if( !SCIPisInfinity(scip, -lhs) )
5505 {
5506 SCIP_Real slack;
5507 SCIP_Real alpha;
5508
5509 /* make sure the max activity is reliable */
5510 if( !consdata->validmaxact )
5511 {
5513 }
5514 assert(consdata->validmaxact);
5515
5516 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5517 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5518 {
5519 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5520 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5521
5522 *cutoff = TRUE;
5523 return SCIP_OKAY;
5524 }
5525
5526 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5527
5528 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5529 * it to zero
5530 */
5531 if( !SCIPisPositive(scip, slack) )
5532 slack = 0.0;
5533
5534 alpha = val * (ub - lb);
5535 assert(!SCIPisNegative(scip, alpha));
5536
5537 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5538 {
5539 SCIP_Real newlb;
5540
5541 /* compute new lower bound */
5542 newlb = ub - (slack / val);
5543
5544 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5545
5546 if( *cutoff )
5547 {
5548 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5549 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5550
5551 return SCIP_OKAY;
5552 }
5553 }
5554 }
5555 }
5556 else
5557 {
5558 /* check, if we can tighten the variable's lower bound */
5559 if( !SCIPisInfinity(scip, rhs) )
5560 {
5561 SCIP_Real slack;
5562 SCIP_Real alpha;
5563
5564 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5565 assert(consdata->validminact);
5566
5567 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5568 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5569 {
5570 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5571 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5572
5573 *cutoff = TRUE;
5574 return SCIP_OKAY;
5575 }
5576
5577 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5578
5579 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5580 * it to zero
5581 */
5582 if( !SCIPisPositive(scip, slack) )
5583 slack = 0.0;
5584
5585 alpha = val * (lb - ub);
5586 assert(!SCIPisNegative(scip, alpha));
5587
5588 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5589 {
5590 SCIP_Real newlb;
5591
5592 /* compute new lower bound */
5593 newlb = ub + slack / val;
5594
5595 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5596
5597 if( *cutoff )
5598 {
5599 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5600 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5601
5602 return SCIP_OKAY;
5603 }
5604 /* collect the new lower bound which is needed for the upper bound computation */
5605 lb = SCIPvarGetLbLocal(var);
5606 }
5607 }
5608
5609 /* check, if we can tighten the variable's upper bound */
5610 if( !SCIPisInfinity(scip, -lhs) )
5611 {
5612 SCIP_Real slack;
5613 SCIP_Real alpha;
5614
5615 /* make sure the max activity is reliable */
5616 if( !consdata->validmaxact )
5617 {
5619 }
5620 assert(consdata->validmaxact);
5621
5622 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5623 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5624 {
5625 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5626 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5627
5628 *cutoff = TRUE;
5629 return SCIP_OKAY;
5630 }
5631
5632 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5633
5634 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5635 * it to zero
5636 */
5637 if( !SCIPisPositive(scip, slack) )
5638 slack = 0.0;
5639
5640 alpha = val * (lb - ub);
5641 assert(!SCIPisNegative(scip, alpha));
5642
5643 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5644 {
5645 SCIP_Real newub;
5646
5647 /* compute new upper bound */
5648 newub = lb - (slack / val);
5649
5650 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5651
5652 if( *cutoff )
5653 {
5654 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5655 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5656
5657 return SCIP_OKAY;
5658 }
5659 }
5660 }
5661 }
5662
5663 return SCIP_OKAY;
5664}
5665
5666/** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5667static
5669 SCIP* scip, /**< SCIP data structure */
5670 SCIP_CONS* cons, /**< conflict detecting constraint */
5671 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5672 int nvars, /**< number of variables reasoning the infeasibility */
5673 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5674 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5675 )
5676{
5677#ifndef NDEBUG
5678 SCIP_CONSDATA* consdata;
5679
5680 assert(scip != NULL);
5681 assert(cons != NULL);
5682
5683 consdata = SCIPconsGetData(cons);
5684 assert(consdata != NULL);
5685 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5686#endif
5687
5688 /* conflict analysis can only be applied in solving stage and if it is turned on */
5690 return SCIP_OKAY;
5691
5692 /* initialize conflict analysis */
5694
5695 /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5697
5698 /* add reasoning variables to conflict candidate queue which led to the conflict */
5699 SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5700
5701 /* analyze the conflict */
5703
5704 return SCIP_OKAY;
5705}
5706
5707/** propagate ranged rows
5708 *
5709 * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5710 * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5711 * variables better.
5712 *
5713 * Example:
5714 * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5715 *
5716 * x3 needs to be a multiple of 3, so the instance is infeasible.
5717 *
5718 * Example:
5719 * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5720 *
5721 * The only possible value for x3 is 2, so the variable will be fixed.
5722 *
5723 * @todo add holes if possible
5724 */
5725static
5727 SCIP* scip, /**< SCIP data structure */
5728 SCIP_CONS* cons, /**< linear constraint */
5729 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5730 int* nfixedvars, /**< pointer to count number of fixed variables */
5731 int* nchgbds, /**< pointer to count the number of bound changes */
5732 int* naddconss /**< pointer to count number of added constraints */
5733 )
5734{
5735 SCIP_CONSHDLRDATA* conshdlrdata;
5736 SCIP_CONSHDLR* conshdlr;
5737 SCIP_CONSDATA* consdata;
5738 SCIP_VAR** infcheckvars;
5739 SCIP_Real* infcheckvals;
5740 SCIP_Real minactinfvars;
5741 SCIP_Real maxactinfvars;
5742 SCIP_Real lb;
5743 SCIP_Real ub;
5744 SCIP_Real feastol;
5745 SCIP_Real fixedact;
5746 SCIP_Real lhs;
5747 SCIP_Real rhs;
5748 SCIP_Real absminbincoef;
5749 SCIP_Longint gcd;
5750 SCIP_Longint gcdtmp;
5751 SCIP_Bool minactinfvarsinvalid;
5752 SCIP_Bool maxactinfvarsinvalid;
5753 SCIP_Bool possiblegcd;
5754 SCIP_Bool gcdisone;
5755 SCIP_Bool addartconss;
5756 int ninfcheckvars;
5757 int nunfixedvars;
5758 int nfixedconsvars;
5759 int ncontvars;
5760 int pos;
5761 int v;
5762
5763 assert(scip != NULL);
5764 assert(cons != NULL);
5765 assert(cutoff != NULL);
5766 assert(nfixedvars != NULL);
5767 assert(nchgbds != NULL);
5768 assert(naddconss != NULL);
5769
5770 /* modifiable constraint can be changed so we do not have all necessary information */
5771 if( SCIPconsIsModifiable(cons) )
5772 return SCIP_OKAY;
5773
5774 consdata = SCIPconsGetData(cons);
5775 assert(consdata != NULL);
5776
5777 /* we already did full ranged row propagation */
5778 if( consdata->rangedrowpropagated == 2 )
5779 return SCIP_OKAY;
5780
5781 /* at least three variables are needed */
5782 if( consdata->nvars < 3 )
5783 return SCIP_OKAY;
5784
5785 /* do nothing on normal inequalities */
5786 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5787 return SCIP_OKAY;
5788
5789 /* get constraint handler data */
5790 conshdlr = SCIPconsGetHdlr(cons);
5791 assert(conshdlr != NULL);
5792 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5793 assert(conshdlrdata != NULL);
5794
5795 addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5796
5797 /* we may add artificial constraints */
5798 if( addartconss )
5799 consdata->rangedrowpropagated = 2;
5800 /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5801 * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5802 * artificial constraints
5803 */
5804 else
5805 {
5806 if( consdata->rangedrowpropagated > 0 )
5807 return SCIP_OKAY;
5808
5809 consdata->rangedrowpropagated = 1;
5810 }
5811 fixedact = 0;
5812 nfixedconsvars = 0;
5813 /* calculate fixed activity and number of fixed variables */
5814 for( v = consdata->nvars - 1; v >= 0; --v )
5815 {
5816 /* all zero coefficients should be eliminated */
5817 assert(!SCIPisZero(scip, consdata->vals[v]));
5818
5819 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5820 {
5821 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5822 ++nfixedconsvars;
5823 }
5824 }
5825
5826 /* do not work with huge fixed activities */
5827 if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5828 return SCIP_OKAY;
5829
5830 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5831 assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5832 lhs = consdata->lhs - fixedact;
5833 rhs = consdata->rhs - fixedact;
5834 nunfixedvars = consdata->nvars - nfixedconsvars;
5835
5836 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5837 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5838 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5839
5840 absminbincoef = SCIP_REAL_MAX;
5841 ncontvars = 0;
5842 gcdisone = TRUE;
5843 possiblegcd = TRUE;
5844
5845 /* we now partition all unfixed variables in two groups:
5846 *
5847 * the first one contains all integral variable with integral
5848 * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5849 * given
5850 *
5851 * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5852 * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5853 */
5854
5855 /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5856 * variables
5857 */
5858 ninfcheckvars = 0;
5859 v = -1;
5860 pos = -1;
5861 do
5862 {
5863 ++v;
5864
5865 /* partition the variables, do not change the order of collection, because it might be used later on */
5866 while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5867 !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5868 {
5869 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5870 {
5871 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5872 {
5873 ++ncontvars;
5874 }
5875 else if( SCIPvarIsBinary(consdata->vars[v]) )
5876 {
5877 SCIP_Real absval;
5878
5879 absval = REALABS(consdata->vals[v]);
5880
5881 if( absminbincoef > absval )
5882 absminbincoef = absval;
5883 }
5884
5885 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5886 possiblegcd = FALSE;
5887 infcheckvars[ninfcheckvars] = consdata->vars[v];
5888 infcheckvals[ninfcheckvars] = consdata->vals[v];
5889 ++ninfcheckvars;
5890
5891 if( pos == -1 )
5892 pos = v;
5893 }
5894 ++v;
5895 }
5896 }
5897 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5898
5899 /* if the first group of variables is empty, we stop */
5900 /* @todo try to propagate/split up a constraint of the form:
5901 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5902 * 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]
5903 */
5904 if( v == consdata->nvars )
5905 goto TERMINATE;
5906
5907 /* we need at least two non-continuous variables */
5908 if( ncontvars + 2 > nunfixedvars )
5909 goto TERMINATE;
5910
5911 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5912 assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
5913
5914 feastol = SCIPfeastol(scip);
5915
5916 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5917 assert(gcd >= 2);
5918
5919 /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5920 * calculate gcd over the first part of variables */
5921 for( ; v < consdata->nvars; ++v )
5922 {
5923 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5924 continue;
5925
5926 if( SCIPvarIsBinary(consdata->vars[v]) )
5927 {
5928 SCIP_Real absval;
5929
5930 absval = REALABS(consdata->vals[v]);
5931
5932 if( absminbincoef > absval )
5933 absminbincoef = absval;
5934 }
5935
5936 if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5937 SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5938 {
5939 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5940 ++ncontvars;
5941
5942 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5943 possiblegcd = FALSE;
5944 infcheckvars[ninfcheckvars] = consdata->vars[v];
5945 infcheckvals[ninfcheckvars] = consdata->vals[v];
5946
5947 ++ninfcheckvars;
5948
5949 if( pos == -1 )
5950 pos = v;
5951 }
5952 else
5953 {
5954 assert(REALABS(consdata->vals[v]) > 1.5);
5955
5956 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5957 assert(gcdtmp >= 1);
5958
5959 if( gcdtmp == 1 )
5960 {
5961 infcheckvars[ninfcheckvars] = consdata->vars[v];
5962 infcheckvals[ninfcheckvars] = consdata->vals[v];
5963
5964 ++ninfcheckvars;
5965
5966 if( pos == -1 )
5967 pos = v;
5968 }
5969 else
5970 gcd = gcdtmp;
5971 }
5972 }
5973 assert(gcd >= 2);
5974
5975 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5976 * normalizeCons() */
5977 if( ninfcheckvars == 0 )
5978 goto TERMINATE;
5979
5980 assert(pos >= 0);
5981
5982 minactinfvarsinvalid = FALSE;
5983 maxactinfvarsinvalid = FALSE;
5984 maxactinfvars = 0.0;
5985 minactinfvars = 0.0;
5986
5987 /* calculate activities over all infcheckvars */
5988 for( v = ninfcheckvars - 1; v >= 0; --v )
5989 {
5990 lb = SCIPvarGetLbLocal(infcheckvars[v]);
5991 ub = SCIPvarGetUbLocal(infcheckvars[v]);
5992
5993 if( SCIPisInfinity(scip, -lb) )
5994 {
5995 if( infcheckvals[v] < 0.0 )
5996 maxactinfvarsinvalid = TRUE;
5997 else
5998 minactinfvarsinvalid = TRUE;
5999 }
6000 else
6001 {
6002 if( infcheckvals[v] < 0.0 )
6003 maxactinfvars += infcheckvals[v] * lb;
6004 else
6005 minactinfvars += infcheckvals[v] * lb;
6006 }
6007
6008 if( SCIPisInfinity(scip, ub) )
6009 {
6010 if( infcheckvals[v] > 0.0 )
6011 maxactinfvarsinvalid = TRUE;
6012 else
6013 minactinfvarsinvalid = TRUE;
6014 }
6015 else
6016 {
6017 if( infcheckvals[v] > 0.0 )
6018 maxactinfvars += infcheckvals[v] * ub;
6019 else
6020 minactinfvars += infcheckvals[v] * ub;
6021 }
6022
6023 /* better abort on to big values */
6024 if( SCIPisHugeValue(scip, -minactinfvars) )
6025 minactinfvarsinvalid = TRUE;
6026 if( SCIPisHugeValue(scip, maxactinfvars) )
6027 maxactinfvarsinvalid = TRUE;
6028
6029 if( minactinfvarsinvalid || maxactinfvarsinvalid )
6030 goto TERMINATE;
6031 }
6032 assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6033
6034 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6035 minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6036
6037 /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6038 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6039 * activities */
6040 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6041 * !!!note!!!
6042 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6043 * are not at their global bound
6044 */
6045
6046 /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6047 * infeasibility */
6048 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6049 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6050 {
6051 SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6053
6054 /* start conflict analysis */
6055 /* @todo improve conflict analysis by adding relaxed bounds */
6056 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6057
6058 *cutoff = TRUE;
6059 }
6060 else if( ncontvars == 0 )
6061 {
6062 SCIP_Longint gcdinfvars = -1;
6063
6064 /* check for gcd over all infcheckvars */
6065 if( possiblegcd )
6066 {
6067 v = ninfcheckvars - 1;
6068 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6069 assert(gcdinfvars >= 2);
6070
6071 for( ; v >= 0 && gcdinfvars >= 2; --v )
6072 {
6073 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6074 }
6075 }
6076 else if( gcdisone )
6077 gcdinfvars = 1;
6078
6079 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6080
6081 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6082 if( gcdinfvars >= 1 )
6083 {
6084 SCIP_Real value;
6085 SCIP_Real value2;
6086 SCIP_Real minvalue = SCIP_INVALID;
6087 SCIP_Real maxvalue = SCIP_INVALID;
6088 int nsols = 0;
6089
6090 value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6091
6092 /* check how many possible solutions exist */
6093 while( SCIPisLE(scip, value, maxactinfvars) )
6094 {
6095 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6096
6097 /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6098 if( !SCIPisGE(scip, value2, lhs) )
6099 {
6100 value2 += gcd;
6101 }
6102
6103 if( SCIPisLE(scip, value2, rhs) )
6104 {
6105 ++nsols;
6106
6107 /* early termination if we found more than two solutions */
6108 if( nsols == 3 )
6109 break;
6110
6111 if( minvalue == SCIP_INVALID ) /*lint !e777*/
6112 minvalue = value;
6113
6114 maxvalue = value;
6115 }
6116 value += gcdinfvars;
6117 }
6118 assert(nsols < 2 || minvalue <= maxvalue);
6119
6120 /* determine last possible solution for better bounding */
6121 if( nsols == 3 )
6122 {
6123#ifndef NDEBUG
6124 SCIP_Real secondsolval = maxvalue;
6125#endif
6126 value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6127
6128 /* check how many possible solutions exist */
6129 while( SCIPisGE(scip, value, minactinfvars) )
6130 {
6131 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6132
6133 /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6134 if( !SCIPisLE(scip, value2, rhs) )
6135 {
6136 value2 -= gcd;
6137 }
6138
6139 if( SCIPisGE(scip, value2, lhs) )
6140 {
6141 maxvalue = value;
6142 assert(maxvalue > minvalue);
6143 break;
6144 }
6145 value -= gcdinfvars;
6146 }
6147 assert(maxvalue > secondsolval);
6148 }
6149
6150 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6151 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6152
6153 /* no possible solution found */
6154 if( nsols == 0 )
6155 {
6156 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6157 gcdinfvars, gcd, lhs, rhs);
6158 SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6160
6161 /* start conflict analysis */
6162 /* @todo improve conflict analysis by adding relaxed bounds */
6163 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6164
6165 *cutoff = TRUE;
6166 }
6167 /* if only one solution exist we can extract a new constraint or fix variables */
6168 else if( nsols == 1 )
6169 {
6170 assert(minvalue == maxvalue); /*lint !e777*/
6171
6172 /* we can fix the only variable in our second set of variables */
6173 if( ninfcheckvars == 1 )
6174 {
6175 SCIP_Bool fixed;
6176
6177 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6178
6179 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6180 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6181 SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6182
6183 /* fix variable to only possible value */
6184 SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6185 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6186
6187 if( *cutoff )
6188 {
6189 /* start conflict analysis */
6190 /* @todo improve conflict analysis by adding relaxed bounds */
6191 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6192 }
6193
6194 if( fixed )
6195 ++(*nfixedvars);
6196 }
6197 else
6198 {
6199 /* check for exactly one unfixed variable which is not part of the infcheckvars */
6200 if( ninfcheckvars == nunfixedvars - 1 )
6201 {
6203 SCIP_Bool foundvar = FALSE;
6204 SCIP_Bool fixed;
6205 int w = 0;
6206
6207 assert(ninfcheckvars > 0);
6208
6209 /* find variable which is not an infcheckvar and fix it */
6210 for( v = 0; v < consdata->nvars - 1; ++v )
6211 {
6212 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6213 {
6214 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6215 {
6216#ifndef NDEBUG
6217 int v2 = v + 1;
6218 int w2 = w;
6219
6220 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6221
6222 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6223 {
6224 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6225 continue;
6226
6227 assert(consdata->vars[v2] == infcheckvars[w2]);
6228 ++w2;
6229 }
6230 assert(w2 == ninfcheckvars);
6231#endif
6232 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6233
6234 foundvar = TRUE;
6235
6236 if( consdata->vals[v] < 0 )
6237 {
6238 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6239 }
6240 else
6241 {
6242 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6243 }
6244
6245 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6246 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6247 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6248
6249 /* fix variable to only possible value */
6250 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6251 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6252
6253 if( *cutoff )
6254 {
6255 /* start conflict analysis */
6256 /* @todo improve conflict analysis by adding relaxed bounds */
6257 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6258 consdata->vars[v], bound) );
6259 }
6260
6261 if( fixed )
6262 ++(*nfixedvars);
6263
6264 break;
6265 }
6266
6267 ++w;
6268 }
6269 }
6270
6271 /* maybe last variable was the not infcheckvar */
6272 if( !foundvar )
6273 {
6274 assert(v == consdata->nvars - 1);
6275 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6276
6277 if( consdata->vals[v] < 0 )
6278 {
6279 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6280 }
6281 else
6282 {
6283 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6284 }
6285
6286 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6287 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6288 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6289
6290 /* fix variable to only possible value */
6291 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6292 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6293
6294 if( *cutoff )
6295 {
6296 /* start conflict analysis */
6297 /* @todo improve conflict analysis by adding relaxed bounds */
6298 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6299 consdata->vars[v], bound) );
6300 }
6301
6302 if( fixed )
6303 ++(*nfixedvars);
6304 }
6305 }
6306 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6307 {
6308 /* aggregation possible if we have two variables, but this will be done later on */
6309 SCIP_CONS* newcons;
6310 char name[SCIP_MAXSTRLEN];
6311
6312 /* create, add, and release new artificial constraint */
6313 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6314 ++conshdlrdata->naddconss;
6315
6316 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6317
6318 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6319 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6320 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6321
6322 SCIPdebugPrintCons(scip, newcons, NULL);
6323
6324 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6325
6326 ++(*naddconss);
6327 }
6328 }
6329 }
6330 /* at least two solutions */
6331 else
6332 {
6333 /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6334
6335 /* only one variable in the second set, so we can bound this variables */
6336 if( ninfcheckvars == 1 )
6337 {
6338 SCIP_Bool tightened;
6339 SCIP_Real newlb;
6340 SCIP_Real newub;
6341
6342 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6343
6344 if( infcheckvals[0] < 0 )
6345 {
6346 newlb = maxvalue/infcheckvals[0];
6347 newub = minvalue/infcheckvals[0];
6348 }
6349 else
6350 {
6351 newlb = minvalue/infcheckvals[0];
6352 newub = maxvalue/infcheckvals[0];
6353 }
6354 assert(newlb < newub);
6355
6356 if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6357 {
6358 /* update lower bound of variable */
6359 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6360 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6361
6362 /* tighten variable lower bound to minimal possible value */
6363 SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6364 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6365
6366 if( *cutoff )
6367 {
6368 /* start conflict analysis */
6369 /* @todo improve conflict analysis by adding relaxed bounds */
6370 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6371 }
6372
6373 if( tightened )
6374 ++(*nchgbds);
6375 }
6376
6377 if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6378 {
6379 /* update upper bound of variable */
6380 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6381 SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6382
6383 /* tighten variable upper bound to maximal possible value */
6384 SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6385 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6386
6387 if( *cutoff )
6388 {
6389 /* start conflict analysis */
6390 /* @todo improve conflict analysis by adding relaxed bounds */
6391 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6392 }
6393
6394 if( tightened )
6395 ++(*nchgbds);
6396 }
6397 }
6398 /* check if we have only one not infcheckvars, if so we can tighten this variable */
6399 else if( ninfcheckvars == nunfixedvars - 1 )
6400 {
6401 SCIP_Bool foundvar = FALSE;
6402 SCIP_Bool tightened;
6403 SCIP_Real newlb;
6404 SCIP_Real newub;
6405 int w = 0;
6406
6407 assert(ninfcheckvars > 0);
6408 assert(minvalue < maxvalue);
6409
6410 /* find variable which is not an infcheckvar and fix it */
6411 for( v = 0; v < consdata->nvars - 1; ++v )
6412 {
6413 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6414 {
6415 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6416 {
6417#ifndef NDEBUG
6418 int v2 = v + 1;
6419 int w2 = w;
6420
6421 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6422
6423 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6424 {
6425 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6426 continue;
6427
6428 assert(consdata->vars[v2] == infcheckvars[w2]);
6429 ++w2;
6430 }
6431 assert(w2 == ninfcheckvars);
6432#endif
6433
6434 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6435 foundvar = TRUE;
6436
6437 if( consdata->vals[v] < 0 )
6438 {
6439 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6440 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6441 }
6442 else
6443 {
6444 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6445 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6446 }
6447 assert(SCIPisLE(scip, newlb, newub));
6448
6449 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6450 {
6451 /* update lower bound of variable */
6452 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6453 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6454
6455 /* tighten variable lower bound to minimal possible value */
6456 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6457 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6458
6459 if( *cutoff )
6460 {
6461 /* start conflict analysis */
6462 /* @todo improve conflict analysis by adding relaxed bounds */
6463 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6464 consdata->vars[v], newlb) );
6465 }
6466
6467 if( tightened )
6468 ++(*nchgbds);
6469 }
6470
6471 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6472 {
6473 /* update upper bound of variable */
6474 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6475 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6476
6477 /* tighten variable upper bound to maximal possible value */
6478 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6479 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6480
6481 if( *cutoff )
6482 {
6483 /* start conflict analysis */
6484 /* @todo improve conflict analysis by adding relaxed bounds */
6485 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6486 consdata->vars[v], newub) );
6487 }
6488
6489 if( tightened )
6490 ++(*nchgbds);
6491 }
6492
6493 break;
6494 }
6495
6496 ++w;
6497 }
6498 }
6499
6500 /* maybe last variable was the not infcheckvar */
6501 if( !foundvar )
6502 {
6503 assert(v == consdata->nvars - 1);
6504 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6505
6506 if( consdata->vals[v] < 0 )
6507 {
6508 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6509 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6510 }
6511 else
6512 {
6513 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6514 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6515 }
6516 assert(SCIPisLE(scip, newlb, newub));
6517
6518 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6519 {
6520 /* update lower bound of variable */
6521 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6522 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6523
6524 /* tighten variable lower bound to minimal possible value */
6525 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6526 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6527
6528 if( *cutoff )
6529 {
6530 /* start conflict analysis */
6531 /* @todo improve conflict analysis by adding relaxed bounds */
6532 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6533 }
6534
6535 if( tightened )
6536 ++(*nchgbds);
6537 }
6538
6539 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6540 {
6541 /* update upper bound of variable */
6542 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6543 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6544
6545 /* tighten variable upper bound to maximal possible value */
6546 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6547 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6548
6549 if( *cutoff )
6550 {
6551 /* start conflict analysis */
6552 /* @todo improve conflict analysis by adding relaxed bounds */
6553 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6554 }
6555
6556 if( tightened )
6557 ++(*nchgbds);
6558 }
6559 }
6560 }
6561 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6562 * region for our infcheckvars, if possible
6563 */
6564 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6565 {
6566 SCIP_CONS* newcons;
6567 char name[SCIP_MAXSTRLEN];
6568 SCIP_Real newlhs;
6569 SCIP_Real newrhs;
6570
6571 assert(maxvalue > minvalue);
6572
6573 if( SCIPisGT(scip, minvalue, minactinfvars) )
6574 newlhs = minvalue;
6575 else
6576 newlhs = -SCIPinfinity(scip);
6577
6578 if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6579 newrhs = maxvalue;
6580 else
6581 newrhs = SCIPinfinity(scip);
6582
6583 if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6584 {
6585 /* create, add, and release new artificial constraint */
6586 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6587 ++conshdlrdata->naddconss;
6588
6589 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6590
6591 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6593 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6594
6595 SCIPdebugPrintCons(scip, newcons, NULL);
6596 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6597
6598 ++(*naddconss);
6599 }
6600 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6601 * should be maxvalue */
6602 }
6603 }
6604 }
6605 }
6606 else if( addartconss && ncontvars < ninfcheckvars )
6607 {
6608 SCIP_Real maxact = 0.0;
6609 SCIP_Real minact = 0.0;
6610 int w = 0;
6611
6612 /* compute activities of non-infcheckvars */
6613 for( v = 0; v < consdata->nvars; ++v )
6614 {
6615 if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6616 {
6617 ++w;
6618 continue;
6619 }
6620
6621 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6622 {
6623 if( SCIPvarIsBinary(consdata->vars[v]) )
6624 {
6625 if( consdata->vals[v] > 0.0 )
6626 maxact += consdata->vals[v];
6627 else
6628 minact += consdata->vals[v];
6629 }
6630 else
6631 {
6632 SCIP_Real tmpval;
6633
6634 assert(SCIPvarIsIntegral(consdata->vars[v]));
6635
6636 if( consdata->vals[v] > 0.0 )
6637 {
6638 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6639
6640 if( SCIPisHugeValue(scip, -tmpval) )
6641 break;
6642
6643 minact += tmpval;
6644
6645 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6646
6647 if( SCIPisHugeValue(scip, tmpval) )
6648 break;
6649
6650 maxact += tmpval;
6651 }
6652 else
6653 {
6654 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6655
6656 if( SCIPisHugeValue(scip, -tmpval) )
6657 break;
6658
6659 minact += tmpval;
6660
6661 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6662
6663 if( SCIPisHugeValue(scip, tmpval) )
6664 break;
6665
6666 maxact += tmpval;
6667 }
6668 }
6669 }
6670 }
6671 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6672 {
6673 SCIP_CONS* newcons;
6674 char name[SCIP_MAXSTRLEN];
6675 SCIP_Real newlhs;
6676 SCIP_Real newrhs;
6677
6678 assert(maxact > minact);
6679 assert(w == ninfcheckvars);
6680
6681 newlhs = lhs - maxact;
6682 newrhs = rhs - minact;
6683 assert(newlhs < newrhs);
6684
6685 /* create, add, and release new artificial constraint */
6686 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6687 ++conshdlrdata->naddconss;
6688
6689 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6690
6691 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6693 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6694
6695 SCIPdebugPrintCons(scip, newcons, NULL);
6696 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6697
6698 ++(*naddconss);
6699 }
6700 }
6701
6702 TERMINATE:
6703 SCIPfreeBufferArray(scip, &infcheckvals);
6704 SCIPfreeBufferArray(scip, &infcheckvars);
6705
6706 return SCIP_OKAY;
6707}
6708
6709/** tightens bounds of a single variable due to activity bounds */
6710static
6712 SCIP* scip, /**< SCIP data structure */
6713 SCIP_CONS* cons, /**< linear constraint */
6714 int pos, /**< position of the variable in the vars array */
6715 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6716 int* nchgbds, /**< pointer to count the total number of tightened bounds */
6717 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6718 )
6719{
6720 SCIP_CONSDATA* consdata;
6721 SCIP_VAR* var;
6722 SCIP_Real val;
6723 SCIP_Real lb;
6724 SCIP_Real ub;
6725 SCIP_Real minresactivity;
6726 SCIP_Real maxresactivity;
6727 SCIP_Real lhs;
6728 SCIP_Real rhs;
6729 SCIP_Bool infeasible;
6730 SCIP_Bool tightened;
6731 SCIP_Bool ismintight;
6732 SCIP_Bool ismaxtight;
6733 SCIP_Bool isminsettoinfinity;
6734 SCIP_Bool ismaxsettoinfinity;
6735
6736 assert(scip != NULL);
6737 assert(cons != NULL);
6738 assert(cutoff != NULL);
6739 assert(nchgbds != NULL);
6740
6741 /* we cannot tighten variables' bounds, if the constraint may be not complete */
6742 if( SCIPconsIsModifiable(cons) )
6743 return SCIP_OKAY;
6744
6745 consdata = SCIPconsGetData(cons);
6746 assert(consdata != NULL);
6747 assert(0 <= pos && pos < consdata->nvars);
6748
6749 *cutoff = FALSE;
6750
6751 var = consdata->vars[pos];
6752
6753 /* we cannot tighten bounds of multi-aggregated variables */
6755 return SCIP_OKAY;
6756
6757 val = consdata->vals[pos];
6758 lhs = consdata->lhs;
6759 rhs = consdata->rhs;
6760 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6761 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
6762 assert(var != NULL);
6763 assert(!SCIPisZero(scip, val));
6764 assert(!SCIPisInfinity(scip, lhs));
6765 assert(!SCIPisInfinity(scip, -rhs));
6766
6767 lb = SCIPvarGetLbLocal(var);
6768 ub = SCIPvarGetUbLocal(var);
6769 assert(SCIPisLE(scip, lb, ub));
6770
6771 if( val > 0.0 )
6772 {
6773 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6774 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6775 */
6776 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6777 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6778 {
6779 SCIP_Real newub;
6780
6781 newub = (rhs - minresactivity)/val;
6782
6783 if( !SCIPisInfinity(scip, newub) &&
6784 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6785 {
6786 SCIP_Bool activityunreliable;
6787 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6788
6789 /* check minresactivities for reliability */
6790 if( activityunreliable )
6791 {
6792 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6793 newub = (rhs - minresactivity)/val;
6794 activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6795 (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6796 && (!force || !SCIPisLT(scip, newub, ub)));
6797 }
6798
6799 if( !activityunreliable )
6800 {
6801 /* tighten upper bound */
6802 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6803 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6804 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6805 &infeasible, &tightened) );
6806 if( infeasible )
6807 {
6808 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6809 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6810
6811 /* analyze conflict */
6813
6814 *cutoff = TRUE;
6815 return SCIP_OKAY;
6816 }
6817 if( tightened )
6818 {
6819 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6820 assert(SCIPisFeasLE(scip, ub, newub));
6821 (*nchgbds)++;
6822
6823 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6824 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6825 }
6826 }
6827 }
6828 }
6829
6830 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6831 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6832 {
6833 SCIP_Real newlb;
6834
6835 newlb = (lhs - maxresactivity)/val;
6836 if( !SCIPisInfinity(scip, -newlb) &&
6837 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6838 {
6839 /* check maxresactivities for reliability */
6840 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6841 {
6842 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6843 newlb = (lhs - maxresactivity)/val;
6844
6845 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6846 && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6847 && (!force || !SCIPisGT(scip, newlb, lb))) )
6848 return SCIP_OKAY;
6849 }
6850
6851 /* tighten lower bound */
6852 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6853 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6854 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6855 &infeasible, &tightened) );
6856 if( infeasible )
6857 {
6858 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6859 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6860
6861 /* analyze conflict */
6863
6864 *cutoff = TRUE;
6865 return SCIP_OKAY;
6866 }
6867 if( tightened )
6868 {
6869 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6870 assert(SCIPisFeasGE(scip, lb, newlb));
6871 (*nchgbds)++;
6872 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6873 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6874 }
6875 }
6876 }
6877 }
6878 else
6879 {
6880 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6881 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6882 */
6883 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6884 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6885 {
6886 SCIP_Real newlb;
6887
6888 newlb = (rhs - minresactivity)/val;
6889 if( !SCIPisInfinity(scip, -newlb) &&
6890 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6891 {
6892 SCIP_Bool activityunreliable;
6893 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6894 /* check minresactivities for reliability */
6895 if( activityunreliable )
6896 {
6897 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6898 newlb = (rhs - minresactivity)/val;
6899
6900 activityunreliable = SCIPisInfinity(scip, -minresactivity)
6901 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6902 && (!force || !SCIPisGT(scip, newlb, lb)));
6903 }
6904
6905 if( !activityunreliable )
6906 {
6907 /* tighten lower bound */
6908 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6909 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6910 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, 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), newlb, ub);
6916
6917 /* analyze conflict */
6919
6920 *cutoff = TRUE;
6921 return SCIP_OKAY;
6922 }
6923 if( tightened )
6924 {
6925 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6926 assert(SCIPisFeasGE(scip, lb, newlb));
6927 (*nchgbds)++;
6928 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6929 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6930 }
6931 }
6932 }
6933 }
6934
6935 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6936 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6937 {
6938 SCIP_Real newub;
6939
6940 newub = (lhs - maxresactivity)/val;
6941 if( !SCIPisInfinity(scip, newub) &&
6942 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, 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 newub = (lhs - maxresactivity)/val;
6949
6950 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6951 && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6952 && (!force || !SCIPisLT(scip, newub, ub))) )
6953 return SCIP_OKAY;
6954 }
6955
6956 /* tighten upper bound */
6957 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6958 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6959 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, 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), lb, newub);
6965
6966 /* analyze conflict */
6968
6969 *cutoff = TRUE;
6970 return SCIP_OKAY;
6971 }
6972 if( tightened )
6973 {
6974 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6975 assert(SCIPisFeasLE(scip, ub, newub));
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
6984 return SCIP_OKAY;
6985}
6986
6987#define MAXTIGHTENROUNDS 10
6988
6989/** tightens bounds of variables in constraint due to activity bounds */
6990static
6992 SCIP* scip, /**< SCIP data structure */
6993 SCIP_CONS* cons, /**< linear constraint */
6994 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
6995 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6996 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6997 int* nchgbds /**< pointer to count the total number of tightened bounds */
6998 )
6999{
7000 SCIP_CONSDATA* consdata;
7001 unsigned int tightenmode;
7002 int nvars;
7003 int nrounds;
7004 int lastchange;
7005 int oldnchgbds;
7006#ifndef SCIP_DEBUG
7007 int oldnchgbdstotal;
7008#endif
7009 int v;
7010 SCIP_Bool force;
7011 SCIP_Bool easycase;
7012
7013 assert(scip != NULL);
7014 assert(cons != NULL);
7015 assert(nchgbds != NULL);
7016 assert(cutoff != NULL);
7017
7018 *cutoff = FALSE;
7019
7020 /* we cannot tighten variables' bounds, if the constraint may be not complete */
7021 if( SCIPconsIsModifiable(cons) )
7022 return SCIP_OKAY;
7023
7024 /* if a constraint was created after presolve, then it may hold fixed variables
7025 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7026 * thus, ensure here again that variable fixings have been applied
7027 */
7028 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7029 if( *cutoff )
7030 return SCIP_OKAY;
7031
7032 /* check if constraint has any chances of tightening bounds */
7033 if( !canTightenBounds(cons) )
7034 return SCIP_OKAY;
7035
7036 consdata = SCIPconsGetData(cons);
7037 assert(consdata != NULL);
7038
7039 nvars = consdata->nvars;
7040 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7041
7042 /* we are at the root node or during presolving */
7043 if( SCIPgetDepth(scip) < 1 )
7044 tightenmode = 2;
7045 else
7046 tightenmode = 1;
7047
7048 /* stop if we already tightened the constraint and the tightening is not forced */
7049 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7050 return SCIP_OKAY;
7051
7052 /* ensure that the variables are properly sorted */
7053 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7054 {
7055 SCIP_CALL( consdataSort(scip, consdata) );
7056 assert(consdata->coefsorted);
7057 }
7058
7059 /* update maximal activity delta if necessary */
7060 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7062
7063 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7064 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7065 checkMaxActivityDelta(scip, consdata);
7066
7067 /* this may happen if all variables are fixed */
7068 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7069 return SCIP_OKAY;
7070
7071 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7072 {
7073 SCIP_Real slack;
7074 SCIP_Real surplus;
7075 SCIP_Real minactivity;
7076 SCIP_Real maxactivity;
7077 SCIP_Bool ismintight;
7078 SCIP_Bool ismaxtight;
7079 SCIP_Bool isminsettoinfinity;
7080 SCIP_Bool ismaxsettoinfinity;
7081
7082 /* use maximal activity delta to skip propagation (cannot deduce anything) */
7083 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &ismintight, &ismaxtight,
7084 &isminsettoinfinity, &ismaxsettoinfinity);
7085 assert(!SCIPisInfinity(scip, minactivity));
7086 assert(!SCIPisInfinity(scip, -maxactivity));
7087
7088 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7089 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7090
7091 /* check if the constraint will propagate */
7092 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7093 return SCIP_OKAY;
7094 }
7095
7096 /* check if we can use fast implementation for easy and numerically well behaved cases */
7097 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7098
7099 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7100 lastchange = -1;
7101 oldnchgbds = 0;
7102
7103#ifndef SCIP_DEBUG
7104 oldnchgbdstotal = *nchgbds;
7105#endif
7106
7107 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7108 {
7109 /* ensure that the variables are properly sorted
7110 *
7111 * note: it might happen that integer variables become binary during bound tightening at the root node
7112 */
7113 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7114 {
7115 SCIP_CALL( consdataSort(scip, consdata) );
7116 assert(consdata->coefsorted);
7117 }
7118
7119 /* mark the constraint to have the variables' bounds tightened */
7120 consdata->boundstightened = (unsigned int)tightenmode;
7121
7122 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7123 * sorting enables skipping variables
7124 */
7125 v = 0;
7126 while( v < nvars && v != lastchange && !(*cutoff) )
7127 {
7128 oldnchgbds = *nchgbds;
7129
7130 if( easycase )
7131 {
7132 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7133 }
7134 else
7135 {
7136 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7137 }
7138
7139 /* if there was no progress, skip the rest of the binary variables */
7140 if( *nchgbds > oldnchgbds )
7141 {
7142 lastchange = v;
7143 ++v;
7144 }
7145 else if( consdata->coefsorted && v < consdata->nbinvars - 1
7146 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7147 v = consdata->nbinvars;
7148 else
7149 ++v;
7150 }
7151
7152#ifndef SCIP_DEBUG
7153 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7154 *nchgbds - oldnchgbdstotal, nrounds);
7155 oldnchgbdstotal += oldnchgbds;
7156#endif
7157 }
7158
7159#ifndef NDEBUG
7160 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7161 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7162#endif
7163
7164 return SCIP_OKAY;
7165}
7166
7167/** checks linear constraint for feasibility of given solution or current solution */
7168static
7170 SCIP* scip, /**< SCIP data structure */
7171 SCIP_CONS* cons, /**< linear constraint */
7172 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7173 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7174 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7175 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7176 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7177 )
7178{
7179 SCIP_CONSDATA* consdata;
7180 SCIP_Real activity;
7181 SCIP_Real absviol;
7182 SCIP_Real relviol;
7183 SCIP_Real lhsviol;
7184 SCIP_Real rhsviol;
7185
7186 assert(scip != NULL);
7187 assert(cons != NULL);
7188 assert(violated != NULL);
7189
7190 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7192
7193 consdata = SCIPconsGetData(cons);
7194 assert(consdata != NULL);
7195
7196 *violated = FALSE;
7197
7198 if( consdata->row != NULL )
7199 {
7200 if( !checklprows && SCIProwIsInLP(consdata->row) )
7201 return SCIP_OKAY;
7202 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7203 activity = consdataComputePseudoActivity(scip, consdata);
7204 else
7205 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7206 }
7207 else
7208 activity = consdataGetActivity(scip, consdata, sol);
7209
7210 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7211 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7212 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7213 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7214
7215 /* calculate absolute and relative bound violations */
7216 lhsviol = consdata->lhs - activity;
7217 rhsviol = activity - consdata->rhs;
7218
7219 absviol = 0.0;
7220 relviol = 0.0;
7221 if( (lhsviol > 0) && (lhsviol > rhsviol) )
7222 {
7223 absviol = lhsviol;
7224 relviol = SCIPrelDiff(consdata->lhs, activity);
7225 }
7226 else if( rhsviol > 0 )
7227 {
7228 absviol = rhsviol;
7229 relviol = SCIPrelDiff(activity, consdata->rhs);
7230 }
7231
7232 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7233 * return infeasible for safety
7234 */
7235 if( activity == SCIP_INVALID ) /*lint !e777*/
7236 {
7237 assert(sol == NULL);
7238 *violated = TRUE;
7239
7240 /* set violation of invalid pseudo solutions */
7241 absviol = SCIP_INVALID;
7242 relviol = SCIP_INVALID;
7243
7244 /* reset constraint age since we are in enforcement */
7246 }
7247 /* check with relative tolerances (the default) */
7248 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7249 {
7250 /* the "normal" check: one of the two sides is violated */
7251 if( !checkrelmaxabs )
7252 {
7253 *violated = TRUE;
7254
7255 /* only reset constraint age if we are in enforcement */
7256 if( sol == NULL )
7257 {
7259 }
7260 }
7261 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7262 * small compared to the absolute values occurring in the activity
7263 */
7264 else
7265 {
7266 SCIP_Real maxabs;
7267 SCIP_Real coef;
7268 SCIP_Real absval;
7269 SCIP_Real solval;
7270 int v;
7271
7272 maxabs = 1.0;
7273
7274 /* compute maximum absolute value */
7275 for( v = 0; v < consdata->nvars; ++v )
7276 {
7277 if( consdata->vals != NULL )
7278 {
7279 coef = consdata->vals[v];
7280 }
7281 else
7282 coef = 1.0;
7283
7284 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7285 absval = REALABS( coef * solval );
7286 maxabs = MAX( maxabs, absval );
7287 }
7288
7289 /* regard left hand side, first */
7290 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7291 {
7292 /* check whether violation is random noise */
7293 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7294 {
7295 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7296 consdata->lhs - activity, maxabs);
7297 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7298
7299 /* only increase constraint age if we are in enforcement */
7300 if( sol == NULL )
7301 {
7302 SCIP_CALL( SCIPincConsAge(scip, cons) );
7303 }
7304 }
7305 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7306 else if( SCIPisZero(scip, consdata->lhs) )
7307 {
7308 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7309 {
7310 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7311 consdata->lhs - activity, maxabs);
7312 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7313
7314 /* only increase constraint age if we are in enforcement */
7315 if( sol == NULL )
7316 {
7317 SCIP_CALL( SCIPincConsAge(scip, cons) );
7318 }
7319 }
7320 else
7321 {
7322 *violated = TRUE;
7323
7324 /* only reset constraint age if we are in enforcement */
7325 if( sol == NULL )
7326 {
7328 }
7329 }
7330 }
7331 else
7332 {
7333 *violated = TRUE;
7334
7335 /* only reset constraint age if we are in enforcement */
7336 if( sol == NULL )
7337 {
7339 }
7340 }
7341 }
7342
7343 /* now regard right hand side */
7344 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7345 {
7346 /* check whether violation is random noise */
7347 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7348 {
7349 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7350 activity - consdata->rhs, maxabs);
7351 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7352
7353 /* only increase constraint age if we are in enforcement */
7354 if( sol == NULL )
7355 {
7356 SCIP_CALL( SCIPincConsAge(scip, cons) );
7357 }
7358 }
7359 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7360 else if( SCIPisZero(scip, consdata->rhs) )
7361 {
7362 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7363 {
7364 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7365 activity - consdata->rhs, maxabs);
7366 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7367
7368 /* only increase constraint age if we are in enforcement */
7369 if( sol == NULL )
7370 {
7371 SCIP_CALL( SCIPincConsAge(scip, cons) );
7372 }
7373 }
7374 else
7375 {
7376 *violated = TRUE;
7377
7378 /* only reset constraint age if we are in enforcement */
7379 if( sol == NULL )
7380 {
7382 }
7383 }
7384 }
7385 else
7386 {
7387 *violated = TRUE;
7388
7389 /* only reset constraint age if we are in enforcement */
7390 if( sol == NULL )
7391 {
7393 }
7394 }
7395 }
7396 }
7397 }
7398 /* check with absolute tolerances */
7399 else if( consdata->checkabsolute &&
7400 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7401 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7402 {
7403 *violated = TRUE;
7404
7405 /* only reset constraint age if we are in enforcement */
7406 if( sol == NULL )
7407 {
7409 }
7410 }
7411 else
7412 {
7413 /* only increase constraint age if we are in enforcement */
7414 if( sol == NULL )
7415 {
7416 SCIP_CALL( SCIPincConsAge(scip, cons) );
7417 }
7418 }
7419
7420 /* update absolute and relative violation of the solution */
7421 if( sol != NULL )
7422 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7423
7424 return SCIP_OKAY;
7425}
7426
7427/** creates an LP row in a linear constraint data */
7428static
7430 SCIP* scip, /**< SCIP data structure */
7431 SCIP_CONS* cons /**< linear constraint */
7432 )
7433{
7434 SCIP_CONSDATA* consdata;
7435
7436 assert(scip != NULL);
7437 assert(cons != NULL);
7438
7439 consdata = SCIPconsGetData(cons);
7440 assert(consdata != NULL);
7441 assert(consdata->row == NULL);
7442
7443 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7445
7446 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7447
7448 return SCIP_OKAY;
7449}
7450
7451/** adds linear constraint as cut to the LP */
7452static
7454 SCIP* scip, /**< SCIP data structure */
7455 SCIP_CONS* cons, /**< linear constraint */
7456 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7457 )
7458{
7459 SCIP_CONSDATA* consdata;
7460
7461 assert(scip != NULL);
7462 assert(cons != NULL);
7463
7464 consdata = SCIPconsGetData(cons);
7465 assert(consdata != NULL);
7466
7467 if( consdata->row == NULL )
7468 {
7469 if( !SCIPconsIsModifiable(cons) )
7470 {
7471 /* 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
7472 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7473 */
7474 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7475 if( *cutoff )
7476 return SCIP_OKAY;
7477 }
7478
7479 /* convert consdata object into LP row */
7480 SCIP_CALL( createRow(scip, cons) );
7481 }
7482 assert(consdata->row != NULL);
7483
7484 if( consdata->nvars == 0 )
7485 {
7486 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7487 }
7488
7489 /* insert LP row as cut */
7490 if( !SCIProwIsInLP(consdata->row) )
7491 {
7492 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7493 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7494 /* if presolving is turned off, the row might be trivial */
7495 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7496 {
7497 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7498 }
7499#ifndef NDEBUG
7500 else
7501 {
7502 int pr;
7503 int cr;
7504 SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7505 SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7506 assert( pr == 0 || cr == 0 );
7507 }
7508#endif
7509 }
7510
7511 return SCIP_OKAY;
7512}
7513
7514/** adds linear constraint as row to the NLP, if not added yet */
7515static
7517 SCIP* scip, /**< SCIP data structure */
7518 SCIP_CONS* cons /**< linear constraint */
7519 )
7520{
7521 SCIP_CONSDATA* consdata;
7522
7523 assert(SCIPisNLPConstructed(scip));
7524
7525 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7526 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7527 return SCIP_OKAY;
7528
7529 consdata = SCIPconsGetData(cons);
7530 assert(consdata != NULL);
7531
7532 if( consdata->nlrow == NULL )
7533 {
7534 assert(consdata->lhs <= consdata->rhs);
7535
7536 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7537 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7538
7539 assert(consdata->nlrow != NULL);
7540 }
7541
7542 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7543 {
7544 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7545 }
7546
7547 return SCIP_OKAY;
7548}
7549
7550/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7551static
7553 SCIP* scip, /**< SCIP data structure */
7554 SCIP_CONS* cons, /**< linear constraint */
7555 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7556 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7557 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7558 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7559 * the ones with non-zero dual value? */
7560 int* ncuts, /**< pointer to add up the number of found cuts */
7561 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7562 )
7563{
7564 SCIP_CONSDATA* consdata;
7565 SCIP_Bool violated;
7566 int oldncuts;
7567
7568 assert(scip != NULL);
7569 assert(conshdlrdata != NULL);
7570 assert(cons != NULL);
7571 assert(cutoff != NULL);
7572
7573 consdata = SCIPconsGetData(cons);
7574 assert(ncuts != NULL);
7575 assert(consdata != NULL);
7576
7577 oldncuts = *ncuts;
7578 *cutoff = FALSE;
7579
7580 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7581
7582 if( violated )
7583 {
7584 /* insert LP row as cut */
7585 SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7586 (*ncuts)++;
7587 }
7588 else if( !SCIPconsIsModifiable(cons) && separatecards )
7589 {
7590 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7591 if( !separateall && sol == NULL )
7592 {
7593 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7594 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7595 {
7596 SCIP_Real dualsol;
7597
7598 dualsol = SCIProwGetDualsol(consdata->row);
7599 if( SCIPisFeasNegative(scip, dualsol) )
7600 {
7601 if( !SCIPisInfinity(scip, consdata->rhs) )
7602 {
7603 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7604 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7605 }
7606 }
7607 else if( SCIPisFeasPositive(scip, dualsol) )
7608 {
7609 if( !SCIPisInfinity(scip, -consdata->lhs) )
7610 {
7611 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7612 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7613 }
7614 }
7615 }
7616 }
7617 else
7618 {
7619 if( !SCIPisInfinity(scip, consdata->rhs) )
7620 {
7621 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7622 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7623 }
7624 if( !SCIPisInfinity(scip, -consdata->lhs) )
7625 {
7626 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7627 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7628 }
7629 }
7630 }
7631
7632 if( *ncuts > oldncuts )
7633 {
7635 }
7636
7637 return SCIP_OKAY;
7638}
7639
7640/** propagation method for linear constraints */
7641static
7643 SCIP* scip, /**< SCIP data structure */
7644 SCIP_CONS* cons, /**< linear constraint */
7645 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7646 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7647 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7648 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7649 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7650 int* nchgbds /**< pointer to count the total number of tightened bounds */
7651 )
7652{
7653 SCIP_CONSDATA* consdata;
7654 SCIP_Real minactivity;
7655 SCIP_Real maxactivity;
7656 SCIP_Bool isminacttight;
7657 SCIP_Bool ismaxacttight;
7658 SCIP_Bool isminsettoinfinity;
7659 SCIP_Bool ismaxsettoinfinity;
7660
7661 assert(scip != NULL);
7662 assert(cons != NULL);
7663 assert(cutoff != NULL);
7664 assert(nchgbds != NULL);
7665
7666 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7667
7668 consdata = SCIPconsGetData(cons);
7669 assert(consdata != NULL);
7670
7671 if( consdata->eventdata == NULL )
7672 {
7673 SCIP_CONSHDLR* conshdlr;
7674 SCIP_CONSHDLRDATA* conshdlrdata;
7675
7676 conshdlr = SCIPconsGetHdlr(cons);
7677 assert(conshdlr != NULL);
7678
7679 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7680 assert(conshdlrdata != NULL);
7681
7682 /* catch bound change events of variables */
7683 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7684 assert(consdata->eventdata != NULL);
7685 }
7686
7687 *cutoff = FALSE;
7688
7689 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7690 if( !SCIPconsIsModifiable(cons) )
7691 {
7692 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7694 {
7695 SCIP_CALL( SCIPincConsAge(scip, cons) );
7696 }
7697
7698 /* tighten the variable's bounds */
7699 if( tightenbounds )
7700 {
7701 int oldnchgbds;
7702
7703 oldnchgbds = *nchgbds;
7704
7705 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7706
7707 if( *nchgbds > oldnchgbds )
7708 {
7710 }
7711 }
7712
7713 /* propagate ranged rows */
7714 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7715 {
7716 int nfixedvars;
7717 int naddconss;
7718 SCIPdebug( int oldnchgbds = *nchgbds; )
7719
7720 nfixedvars = 0;
7721 naddconss = 0;
7722
7723 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7724
7725 if( *cutoff )
7726 {
7727 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7728 }
7729 else
7730 {
7731 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7732 }
7733
7734 if( nfixedvars > 0 )
7735 *nchgbds += 2*nfixedvars;
7736 } /*lint !e438*/
7737
7738 /* check constraint for infeasibility and redundancy */
7739 if( !(*cutoff) )
7740 {
7741 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
7742 &isminsettoinfinity, &ismaxsettoinfinity);
7743
7744 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7745 {
7746 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7747 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7748
7749 /* analyze conflict */
7751
7753 *cutoff = TRUE;
7754 }
7755 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7756 {
7757 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7758 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7759
7760 /* analyze conflict */
7762
7764 *cutoff = TRUE;
7765 }
7766 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7767 {
7768 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7769 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7770
7771 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7772 if( consdata->nvars > 0 )
7774 else
7775 SCIP_CALL( SCIPdelCons(scip, cons) );
7776 }
7777 }
7778 }
7779
7780 return SCIP_OKAY;
7781}
7782
7783
7784/*
7785 * Presolving methods
7786 */
7787
7788/** converts all variables with fixed domain into FIXED variables */
7789static
7791 SCIP* scip, /**< SCIP data structure */
7792 SCIP_CONS* cons, /**< linear constraint */
7793 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7794 int* nfixedvars /**< pointer to count the total number of fixed variables */
7795 )
7796{
7797 SCIP_CONSDATA* consdata;
7798 SCIP_VAR* var;
7799 SCIP_VARSTATUS varstatus;
7800 SCIP_Real lb;
7801 SCIP_Real ub;
7802 SCIP_Bool fixed;
7803 SCIP_Bool infeasible;
7804 int v;
7805
7806 assert(scip != NULL);
7807 assert(cons != NULL);
7808 assert(cutoff != NULL);
7809 assert(nfixedvars != NULL);
7810
7811 consdata = SCIPconsGetData(cons);
7812 assert(consdata != NULL);
7813
7814 for( v = 0; v < consdata->nvars; ++v )
7815 {
7816 assert(consdata->vars != NULL);
7817 var = consdata->vars[v];
7818 varstatus = SCIPvarGetStatus(var);
7819
7820 if( varstatus != SCIP_VARSTATUS_FIXED )
7821 {
7822 lb = SCIPvarGetLbGlobal(var);
7823 ub = SCIPvarGetUbGlobal(var);
7824 if( SCIPisEQ(scip, lb, ub) )
7825 {
7826 SCIP_Real fixval;
7827
7828 fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7829 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7830 SCIPvarGetName(var), lb, ub, fixval);
7831 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7832 if( infeasible )
7833 {
7834 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7835 *cutoff = TRUE;
7836 return SCIP_OKAY;
7837 }
7838 if( fixed )
7839 (*nfixedvars)++;
7840 }
7841 }
7842 }
7843
7844 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7845
7846 if( infeasible )
7847 {
7848 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7849 *cutoff = TRUE;
7850 return SCIP_OKAY;
7851 }
7852
7853 assert(consdata->removedfixings);
7854
7855 return SCIP_OKAY;
7856}
7857
7858#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7859
7860/** extracts cliques of the constraint and adds them to SCIP
7861 *
7862 * The following clique extraction mechanism are implemeneted
7863 *
7864 * 1. collect binary variables and sort them in non increasing order, then
7865 *
7866 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7867 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7868 * condition
7869 *
7870 * minactivity + vals[i] + vals[i+1] > rhs
7871 *
7872 * and also add the binary to binary implication also for non-successive variables for which the same argument
7873 * holds
7874 *
7875 * minactivity + vals[i] + vals[j] > rhs
7876 *
7877 * 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
7878 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7879 *
7880 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7881 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7882 * condition
7883 *
7884 * maxactivity + vals[i] + vals[i-1] < lhs
7885 *
7886 * and also add the binary to binary implication also for non-successive variables for which the same argument
7887 * holds
7888 *
7889 * maxactivity + vals[i] + vals[j] < lhs
7890 *
7891 * e.g. you could multiply the above example by -1
7892 *
7893 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7894 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7895 * condition
7896 *
7897 * minactivity - vals[i] - vals[i-1] > rhs
7898 *
7899 * and also add the binary to binary implication also for non-successive variables for which the
7900 * same argument holds
7901 *
7902 * minactivity - vals[i] - vals[j] > rhs
7903 *
7904 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7905 * implication x1 = 0 => x3 = 1
7906 *
7907 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7908 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7909 * condition
7910 *
7911 * maxactivity - vals[i] - vals[i+1] < lhs
7912 *
7913 * and also add the binary to binary implication also for non-successive variables for which the same argument
7914 * holds
7915 *
7916 * maxactivity - vals[i] - vals[j] < lhs
7917 *
7918 * e.g. you could multiply the above example by -1
7919 *
7920 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7921 * as clique, (this part is done at the end of the method)
7922 *
7923 */
7924static
7926 SCIP* scip, /**< SCIP data structure */
7927 SCIP_CONS* cons, /**< linear constraint */
7928 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7929 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7930 int* nfixedvars, /**< pointer to count number of fixed variables */
7931 int* nchgbds, /**< pointer to count the total number of tightened bounds */
7932 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7933 )
7934{
7935 SCIP_VAR** vars;
7936 SCIP_Real* vals;
7937 SCIP_CONSDATA* consdata;
7938 SCIP_Bool lhsclique;
7939 SCIP_Bool rhsclique;
7940 SCIP_Bool finitelhs;
7941 SCIP_Bool finiterhs;
7942 SCIP_Bool finiteminact;
7943 SCIP_Bool finitemaxact;
7944 SCIP_Bool finitenegminact;
7945 SCIP_Bool finitenegmaxact;
7946 SCIP_Bool finiteposminact;
7947 SCIP_Bool finiteposmaxact;
7948 SCIP_Bool infeasible;
7949 SCIP_Bool stopped;
7950 int cliquenonzerosadded;
7951 int v;
7952 int i;
7953 int nposcoefs;
7954 int nnegcoefs;
7955 int nvars;
7956
7957 assert(scip != NULL);
7958 assert(cons != NULL);
7959 assert(nfixedvars != NULL);
7960 assert(nchgbds != NULL);
7961 assert(cutoff != NULL);
7962 assert(!SCIPconsIsDeleted(cons));
7963
7964 consdata = SCIPconsGetData(cons);
7965 assert(consdata != NULL);
7966
7967 if( consdata->nvars < 2 )
7968 return SCIP_OKAY;
7969
7970 /* add implications if possible
7971 *
7972 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7973 * maximal absolute contribution and also only if this variable would force all other variables to their bound
7974 * corresponding to the global minimal activity of the constraint
7975 */
7976 if( !consdata->implsadded )
7977 {
7978 /* sort variables by variable type */
7979 SCIP_CALL( consdataSort(scip, consdata) );
7980
7981 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7982 * up front, might change sorting correspondingly
7983 */
7984 /* fast abort if no binaries seem to exist
7985 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
7986 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
7987 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
7988 * which is the requirement for consdataSort() to actually resort the variables
7989 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
7990 */
7991 if( !SCIPvarIsBinary(consdata->vars[0]) )
7992 return SCIP_OKAY;
7993
7994 nvars = consdata->nvars;
7995 vars = consdata->vars;
7996 vals = consdata->vals;
7997
7998 /* recompute activities if needed */
7999 if( !consdata->validactivities )
8000 consdataCalcActivities(scip, consdata);
8001 assert(consdata->validactivities);
8002
8003 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8004 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8005 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8006 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8007 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8008 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8009 finiteminact = (finitenegminact && finiteposminact);
8010 finitemaxact = (finitenegmaxact && finiteposmaxact);
8011
8012 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8013 {
8014 SCIP_Real maxabscontrib = -1.0;
8015 SCIP_Bool posval = FALSE;
8016 SCIP_Bool allbinary = TRUE;
8017 int oldnchgbds = *nchgbds;
8018 int nbdchgs = 0;
8019 int nimpls = 0;
8020 int position = -1;
8021
8022 /* we need a valid minimal/maximal activity to add cliques */
8023 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8024 {
8026 assert(consdata->validglbminact);
8027 }
8028
8029 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8030 {
8032 assert(consdata->validglbmaxact);
8033 }
8034 assert(consdata->validglbminact || consdata->validglbmaxact);
8035
8036 /* @todo extend this to local/constraint probing */
8037
8038 /* determine maximal contribution to the activity */
8039 for( v = nvars - 1; v >= 0; --v )
8040 {
8041 if( SCIPvarIsBinary(vars[v]) )
8042 {
8043 if( vals[v] > 0 )
8044 {
8045 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8046
8047 if( value > maxabscontrib )
8048 {
8049 maxabscontrib = value;
8050 position = v;
8051 posval = TRUE;
8052 }
8053 }
8054 else
8055 {
8056 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8057
8058 value = REALABS(value);
8059
8060 if( value > maxabscontrib )
8061 {
8062 maxabscontrib = value;
8063 position = v;
8064 posval = FALSE;
8065 }
8066 }
8067 }
8068 else
8069 allbinary = FALSE;
8070 }
8071 assert(0 <= position && position < nvars);
8072
8073 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8074 {
8075 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8076 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8077 * implications
8078 */
8079 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8080 {
8081 for( v = nvars - 1; v >= 0; --v )
8082 {
8083 /* binary to binary implications will be collected when extrating cliques */
8084 if( !SCIPvarIsBinary(vars[v]) )
8085 {
8086 if( v != position )
8087 {
8088 if( vals[v] > 0 )
8089 {
8090 /* add implications */
8091 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8092 ++nimpls;
8093 *nchgbds += nbdchgs;
8094 }
8095 else
8096 {
8097 /* add implications */
8098 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8099 ++nimpls;
8100 *nchgbds += nbdchgs;
8101 }
8102
8103 if( infeasible )
8104 {
8105 *cutoff = TRUE;
8106 break;
8107 }
8108 }
8109 }
8110 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8111 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8112 break;
8113 }
8114 }
8115
8116 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8117 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8118 * implications
8119 */
8120 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8121 {
8122 for( v = nvars - 1; v >= 0; --v )
8123 {
8124 /* binary to binary implications will be collected when extrating cliques */
8125 if( !SCIPvarIsBinary(vars[v]) )
8126 {
8127 if( v != position )
8128 {
8129 if( vals[v] > 0 )
8130 {
8131 /* add implications */
8132 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8133 ++nimpls;
8134 *nchgbds += nbdchgs;
8135 }
8136 else
8137 {
8138 /* add implications */
8139 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8140 ++nimpls;
8141 *nchgbds += nbdchgs;
8142 }
8143
8144 if( infeasible )
8145 {
8146 *cutoff = TRUE;
8147 break;
8148 }
8149 }
8150 }
8151 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8152 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8153 break;
8154 }
8155 }
8156
8157 /* did we find some implications */
8158 if( nimpls > 0 )
8159 {
8160 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8161
8162 if( *cutoff )
8163 return SCIP_OKAY;
8164
8165 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8166 if( *nchgbds - oldnchgbds > 0 )
8167 {
8168 /* check for fixed variables */
8169 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8170 if( *cutoff )
8171 return SCIP_OKAY;
8172
8173 /* tighten variable's bounds */
8174 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8175 if( *cutoff )
8176 return SCIP_OKAY;
8177
8178 /* check for fixed variables */
8179 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8180 if( *cutoff )
8181 return SCIP_OKAY;
8182 }
8183 }
8184 }
8185 }
8186
8187 consdata->implsadded = TRUE;
8188 }
8189
8190 /* check if we already added the cliques of this constraint */
8191 if( consdata->cliquesadded )
8192 return SCIP_OKAY;
8193
8194 consdata->cliquesadded = TRUE;
8195 cliquenonzerosadded = 0;
8196 stopped = FALSE;
8197
8198 /* sort variables by variable type */
8199 SCIP_CALL( consdataSort(scip, consdata) );
8200
8201 nvars = consdata->nvars;
8202 vars = consdata->vars;
8203 vals = consdata->vals;
8204
8205 /**@todo extract more cliques, implications and variable bounds from linear constraints */
8206
8207 /* recompute activities if needed */
8208 if( !consdata->validactivities )
8209 consdataCalcActivities(scip, consdata);
8210 assert(consdata->validactivities);
8211
8212 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8213 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8214 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8215 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8216 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8217 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8218 finiteminact = (finitenegminact && finiteposminact);
8219 finitemaxact = (finitenegmaxact && finiteposmaxact);
8220
8221 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8222 * information
8223 */
8224 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8225 {
8226 SCIP_VAR** binvars;
8227 SCIP_Real* binvarvals;
8228 int nposbinvars = 0;
8229 int nnegbinvars = 0;
8230 int allonebinary = 0;
8231
8232 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8233 SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8234
8235 /* collect binary variables */
8236 for( i = 0; i < nvars; ++i )
8237 {
8238 if( SCIPvarIsBinary(vars[i]) )
8239 {
8240 assert(!SCIPisZero(scip, vals[i]));
8241
8242 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8243 ++allonebinary;
8244
8245 binvars[nposbinvars + nnegbinvars] = vars[i];
8246 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8247
8248 if( SCIPisPositive(scip, vals[i]) )
8249 ++nposbinvars;
8250 else
8251 ++nnegbinvars;
8252
8253 assert(nposbinvars + nnegbinvars <= nvars);
8254 }
8255 /* stop searching for binary variables, because the constraint data is sorted */
8256 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8257 break;
8258 }
8259 assert(nposbinvars + nnegbinvars <= nvars);
8260
8261 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8262 * cliques
8263 */
8264 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8265 {
8266 SCIP_Real threshold;
8267 int oldnchgbds = *nchgbds;
8268 int nbdchgs;
8269 int jstart;
8270 int j;
8271
8272 /* we need a valid minimal/maximal activity to add cliques */
8273 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8274 {
8276 assert(consdata->validglbminact);
8277 }
8278
8279 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8280 {
8282 assert(consdata->validglbmaxact);
8283 }
8284 assert(consdata->validglbminact || consdata->validglbmaxact);
8285
8286 /* sort coefficients non-increasing to be faster in the clique search */
8287 SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8288
8289 /* case a) */
8290 if( finiterhs && finitenegminact && nposbinvars >= 2 )
8291 {
8292 /* compute value that needs to be exceeded */
8293 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8294
8295 j = 1;
8296#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8297 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8298 assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8299#endif
8300 /* check if at least two variables are in a clique */
8301 if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8302 {
8303 ++j;
8304 /* check for extending the clique */
8305 while( j < nposbinvars )
8306 {
8307 if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8308 break;
8309 ++j;
8310 }
8311 assert(j >= 2);
8312
8313 /* add clique with at least two variables */
8314 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8315
8316 if( infeasible )
8317 *cutoff = TRUE;
8318
8319 *nchgbds += nbdchgs;
8320
8321 cliquenonzerosadded += j;
8322 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8323 stopped = TRUE;
8324
8325 /* exchange the last variable in the clique if possible and add all new ones */
8326 if( !stopped && !(*cutoff) && j < nposbinvars )
8327 {
8328 SCIP_VAR** clqvars;
8329 int lastfit = j - 2;
8330 assert(lastfit >= 0);
8331
8332 /* copy all 'main'-clique variables */
8333 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8334
8335 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8336 while( lastfit >= 0 && j < nposbinvars )
8337 {
8338 /* check if two variables are in a clique */
8339 if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8340 {
8341 clqvars[lastfit + 1] = binvars[j];
8342
8343 /* add clique with at least two variables */
8344 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8345
8346 if( infeasible )
8347 {
8348 *cutoff = TRUE;
8349 break;
8350 }
8351
8352 *nchgbds += nbdchgs;
8353
8354 cliquenonzerosadded += (lastfit + 2);
8355 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8356 {
8357 stopped = TRUE;
8358 break;
8359 }
8360
8361 ++j;
8362 }
8363 else
8364 --lastfit;
8365 }
8366
8367 SCIPfreeBufferArray(scip, &clqvars);
8368 }
8369 }
8370 }
8371
8372 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8373 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8374 {
8375 /* check for fixed variables */
8376 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8377
8378 if( !*cutoff )
8379 {
8380 /* tighten variable's bounds */
8381 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8382
8383 if( !*cutoff )
8384 {
8385 /* check for fixed variables */
8386 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8387
8388 if( !*cutoff )
8389 {
8390 /* sort variables by variable type */
8391 SCIP_CALL( consdataSort(scip, consdata) );
8392
8393 /* recompute activities if needed */
8394 if( !consdata->validactivities )
8395 consdataCalcActivities(scip, consdata);
8396 assert(consdata->validactivities);
8397
8398 nvars = consdata->nvars;
8399 vars = consdata->vars;
8400 vals = consdata->vals;
8401 nposbinvars = 0;
8402 nnegbinvars = 0;
8403 allonebinary = 0;
8404
8405 /* update binary variables */
8406 for( i = 0; i < nvars; ++i )
8407 {
8408 if( SCIPvarIsBinary(vars[i]) )
8409 {
8410 assert(!SCIPisZero(scip, vals[i]));
8411
8412 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8413 ++allonebinary;
8414
8415 binvars[nposbinvars + nnegbinvars] = vars[i];
8416 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8417
8418 if( SCIPisPositive(scip, vals[i]) )
8419 ++nposbinvars;
8420 else
8421 ++nnegbinvars;
8422
8423 assert(nposbinvars + nnegbinvars <= nvars);
8424 }
8425 /* stop searching for binary variables, because the constraint data is sorted */
8426 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8427 break;
8428 }
8429 assert(nposbinvars + nnegbinvars <= nvars);
8430 }
8431 }
8432 }
8433
8434 oldnchgbds = *nchgbds;
8435 }
8436
8437 /* case b) */
8438 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8439 {
8440 /* compute value that needs to be deceeded */
8441 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8442
8443 i = nposbinvars + nnegbinvars - 1;
8444 j = i - 1;
8445#ifdef SCIP_DISABLED_CODE
8446 /* assertion should only hold when constraints were fully propagated and boundstightened */
8447 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8448 assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8449#endif
8450 /* check if two variables are in a clique */
8451 if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8452 {
8453 --j;
8454 /* check for extending the clique */
8455 while( j >= nposbinvars )
8456 {
8457 if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8458 break;
8459 --j;
8460 }
8461 jstart = j;
8462
8463 assert(i - j >= 2);
8464 /* add clique with at least two variables */
8465 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8466
8467 if( infeasible )
8468 *cutoff = TRUE;
8469
8470 *nchgbds += nbdchgs;
8471
8472 cliquenonzerosadded += (i - j);
8473 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8474 stopped = TRUE;
8475
8476 /* exchange the last variable in the clique if possible and add all new ones */
8477 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8478 {
8479 SCIP_VAR** clqvars;
8480 int lastfit = jstart + 1;
8481 assert(lastfit < i);
8482
8483 /* copy all 'main'-clique variables */
8484 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8485 ++lastfit;
8486
8487 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8488 while( lastfit <= i && j >= nposbinvars )
8489 {
8490 /* check if two variables are in a clique */
8491 if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8492 {
8493 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8494 clqvars[lastfit - jstart - 2] = binvars[j];
8495
8496 assert(i - lastfit + 2 >= 2);
8497 /* add clique with at least two variables */
8498 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8499
8500 if( infeasible )
8501 {
8502 *cutoff = TRUE;
8503 break;
8504 }
8505
8506 *nchgbds += nbdchgs;
8507
8508 cliquenonzerosadded += (i - lastfit + 2);
8509 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8510 {
8511 stopped = TRUE;
8512 break;
8513 }
8514
8515 --j;
8516 }
8517 else
8518 ++lastfit;
8519 }
8520
8521 SCIPfreeBufferArray(scip, &clqvars);
8522 }
8523 }
8524 }
8525
8526 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8527 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8528 {
8529 /* check for fixed variables */
8530 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8531
8532 if( !*cutoff )
8533 {
8534 /* tighten variable's bounds */
8535 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8536
8537 if( !*cutoff )
8538 {
8539 /* check for fixed variables */
8540 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8541
8542 if( !*cutoff )
8543 {
8544 /* sort variables by variable type */
8545 SCIP_CALL( consdataSort(scip, consdata) );
8546
8547 /* recompute activities if needed */
8548 if( !consdata->validactivities )
8549 consdataCalcActivities(scip, consdata);
8550 assert(consdata->validactivities);
8551
8552 nvars = consdata->nvars;
8553 vars = consdata->vars;
8554 vals = consdata->vals;
8555 nposbinvars = 0;
8556 nnegbinvars = 0;
8557 allonebinary = 0;
8558
8559 /* update binary variables */
8560 for( i = 0; i < nvars; ++i )
8561 {
8562 if( SCIPvarIsBinary(vars[i]) )
8563 {
8564 assert(!SCIPisZero(scip, vals[i]));
8565
8566 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8567 ++allonebinary;
8568
8569 binvars[nposbinvars + nnegbinvars] = vars[i];
8570 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8571
8572 if( SCIPisPositive(scip, vals[i]) )
8573 ++nposbinvars;
8574 else
8575 ++nnegbinvars;
8576
8577 assert(nposbinvars + nnegbinvars <= nvars);
8578 }
8579 /* stop searching for binary variables, because the constraint data is sorted */
8580 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8581 break;
8582 }
8583 assert(nposbinvars + nnegbinvars <= nvars);
8584 }
8585 }
8586 }
8587
8588 oldnchgbds = *nchgbds;
8589 }
8590
8591 /* case c) */
8592 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8593 {
8594 SCIP_Bool* values;
8595
8596 /* initialize clique values array for adding a negated clique */
8597 SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8598 BMSclearMemoryArray(values, nnegbinvars);
8599
8600 /* compute value that needs to be exceeded */
8601 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8602
8603 i = nposbinvars + nnegbinvars - 1;
8604 j = i - 1;
8605
8606#ifdef SCIP_DISABLED_CODE
8607 /* assertion should only hold when constraints were fully propagated and boundstightened */
8608 /* check if the variable should not have already been fixed to one */
8609 assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8610#endif
8611
8612 if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8613 {
8614 --j;
8615 /* check for extending the clique */
8616 while( j >= nposbinvars )
8617 {
8618 if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8619 break;
8620 --j;
8621 }
8622 jstart = j;
8623
8624 assert(i - j >= 2);
8625 /* add negated clique with at least two variables */
8626 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8627
8628 if( infeasible )
8629 *cutoff = TRUE;
8630
8631 *nchgbds += nbdchgs;
8632
8633 cliquenonzerosadded += (i - j);
8634 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8635 stopped = TRUE;
8636
8637 /* exchange the last variable in the clique if possible and add all new ones */
8638 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8639 {
8640 SCIP_VAR** clqvars;
8641 int lastfit = j + 1;
8642 assert(lastfit < i);
8643
8644 /* copy all 'main'-clique variables */
8645 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8646 ++lastfit;
8647
8648 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8649 while( lastfit <= i && j >= nposbinvars )
8650 {
8651 /* check if two variables are in a negated clique */
8652 if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8653 {
8654 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8655 clqvars[lastfit - jstart - 2] = binvars[j];
8656
8657 assert(i - lastfit + 2 >= 2);
8658 /* add clique with at least two variables */
8659 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8660
8661 if( infeasible )
8662 {
8663 *cutoff = TRUE;
8664 break;
8665 }
8666
8667 *nchgbds += nbdchgs;
8668
8669 cliquenonzerosadded += (i - lastfit + 2);
8670 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8671 {
8672 stopped = TRUE;
8673 break;
8674 }
8675
8676 --j;
8677 }
8678 else
8679 ++lastfit;
8680 }
8681
8682 SCIPfreeBufferArray(scip, &clqvars);
8683 }
8684 }
8685
8686 SCIPfreeBufferArray(scip, &values);
8687 }
8688
8689 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8690 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8691 {
8692 /* check for fixed variables */
8693 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8694
8695 if( !*cutoff )
8696 {
8697 /* tighten variable's bounds */
8698 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8699
8700 if( !*cutoff )
8701 {
8702 /* check for fixed variables */
8703 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8704
8705 if( !*cutoff )
8706 {
8707 /* sort variables by variable type */
8708 SCIP_CALL( consdataSort(scip, consdata) );
8709
8710 /* recompute activities if needed */
8711 if( !consdata->validactivities )
8712 consdataCalcActivities(scip, consdata);
8713 assert(consdata->validactivities);
8714
8715 nvars = consdata->nvars;
8716 vars = consdata->vars;
8717 vals = consdata->vals;
8718 nposbinvars = 0;
8719 nnegbinvars = 0;
8720 allonebinary = 0;
8721
8722 /* update binary variables */
8723 for( i = 0; i < nvars; ++i )
8724 {
8725 if( SCIPvarIsBinary(vars[i]) )
8726 {
8727 assert(!SCIPisZero(scip, vals[i]));
8728
8729 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8730 ++allonebinary;
8731
8732 binvars[nposbinvars + nnegbinvars] = vars[i];
8733 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8734
8735 if( SCIPisPositive(scip, vals[i]) )
8736 ++nposbinvars;
8737 else
8738 ++nnegbinvars;
8739
8740 assert(nposbinvars + nnegbinvars <= nvars);
8741 }
8742 /* stop searching for binary variables, because the constraint data is sorted */
8743 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8744 break;
8745 }
8746 assert(nposbinvars + nnegbinvars <= nvars);
8747 }
8748 }
8749 }
8750 }
8751
8752 /* case d) */
8753 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8754 {
8755 SCIP_Bool* values;
8756
8757 /* initialize clique values array for adding a negated clique */
8758 SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8759 BMSclearMemoryArray(values, nposbinvars);
8760
8761 /* compute value that needs to be exceeded */
8762 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8763
8764 j = 1;
8765
8766#ifdef SCIP_DISABLED_CODE
8767 /* assertion should only hold when constraints were fully propagated and boundstightened */
8768 /* check if the variable should not have already been fixed to one */
8769 assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8770#endif
8771
8772 if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8773 {
8774 ++j;
8775 /* check for extending the clique */
8776 while( j < nposbinvars )
8777 {
8778 if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8779 break;
8780 ++j;
8781 }
8782 assert(j >= 2);
8783
8784 /* add negated clique with at least two variables */
8785 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8786
8787 if( infeasible )
8788 *cutoff = TRUE;
8789
8790 *nchgbds += nbdchgs;
8791
8792 cliquenonzerosadded += j;
8793 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8794 stopped = TRUE;
8795
8796 /* exchange the last variable in the clique if possible and add all new ones */
8797 if( !stopped && !(*cutoff) && j < nposbinvars )
8798 {
8799 SCIP_VAR** clqvars;
8800 int lastfit = j - 2;
8801 assert(lastfit >= 0);
8802
8803 /* copy all 'main'-clique variables */
8804 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8805
8806 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8807 while( lastfit >= 0 && j < nposbinvars )
8808 {
8809 /* check if two variables are in a negated clique */
8810 if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8811 {
8812 clqvars[lastfit + 1] = binvars[j];
8813
8814 /* add clique with at least two variables */
8815 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8816
8817 if( infeasible )
8818 {
8819 *cutoff = TRUE;
8820 break;
8821 }
8822
8823 *nchgbds += nbdchgs;
8824
8825 cliquenonzerosadded += lastfit + 2;
8826 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8827 break;
8828
8829 ++j;
8830 }
8831 else
8832 --lastfit;
8833 }
8834
8835 SCIPfreeBufferArray(scip, &clqvars);
8836 }
8837 }
8838
8839 SCIPfreeBufferArray(scip, &values);
8840 }
8841 }
8842
8843 SCIPfreeBufferArray(scip, &binvarvals);
8844 SCIPfreeBufferArray(scip, &binvars);
8845
8846 if( *cutoff )
8847 return SCIP_OKAY;
8848 }
8849
8850 /* 2. we only check if the constraint is a set packing / partitioning constraint */
8851
8852 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8853 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8854 */
8855 nposcoefs = 0;
8856 nnegcoefs = 0;
8857 for( i = 0; i < nvars; ++i )
8858 {
8859 if( !SCIPvarIsBinary(vars[i]) )
8860 return SCIP_OKAY;
8861 else if( SCIPisEQ(scip, vals[i], +1.0) )
8862 nposcoefs++;
8863 else if( SCIPisEQ(scip, vals[i], -1.0) )
8864 nnegcoefs++;
8865 else
8866 return SCIP_OKAY;
8867 }
8868
8869 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8870 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8871
8872 if( lhsclique || rhsclique )
8873 {
8874 SCIP_Bool* values;
8875 int nbdchgs;
8876
8877 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8878 SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8879 SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8880
8881 for( i = 0; i < nvars; ++i )
8882 values[i] = (rhsclique == (vals[i] > 0.0));
8883
8884 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8885
8886 if( infeasible )
8887 *cutoff = TRUE;
8888
8889 *nchgbds += nbdchgs;
8890 SCIPfreeBufferArray(scip, &values);
8891 }
8892
8893 return SCIP_OKAY;
8894}
8895
8896/** tightens left and right hand side of constraint due to integrality */
8897static
8899 SCIP* scip, /**< SCIP data structure */
8900 SCIP_CONS* cons, /**< linear constraint */
8901 int* nchgsides, /**< pointer to count number of side changes */
8902 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8903 )
8904{
8905 SCIP_CONSDATA* consdata;
8906 SCIP_Real newlhs;
8907 SCIP_Real newrhs;
8908 SCIP_Bool chglhs;
8909 SCIP_Bool chgrhs;
8910 SCIP_Bool integral;
8911 int i;
8912
8913 assert(scip != NULL);
8914 assert(cons != NULL);
8915 assert(nchgsides != NULL);
8916 assert(infeasible != NULL);
8917
8918 consdata = SCIPconsGetData(cons);
8919 assert(consdata != NULL);
8920
8921 *infeasible = FALSE;
8922
8923 chglhs = FALSE;
8924 chgrhs = FALSE;
8925 newlhs = -SCIPinfinity(scip);
8926 newrhs = SCIPinfinity(scip);
8927
8928 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8929 {
8930 integral = TRUE;
8931 for( i = 0; i < consdata->nvars && integral; ++i )
8932 {
8933 integral = SCIPisIntegral(scip, consdata->vals[i])
8934 && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
8935 }
8936 if( integral )
8937 {
8938 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8939 {
8940 newlhs = SCIPfeasCeil(scip, consdata->lhs);
8941 chglhs = TRUE;
8942 }
8943 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8944 {
8945 newrhs = SCIPfeasFloor(scip, consdata->rhs);
8946 chgrhs = TRUE;
8947 }
8948
8949 /* check whether rounding would lead to an unsatisfiable constraint */
8950 if( SCIPisGT(scip, newlhs, newrhs) )
8951 {
8952 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
8953 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
8954
8955 *infeasible = TRUE;
8956 return SCIP_OKAY;
8957 }
8958
8959 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8960 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8961
8962 if( chglhs )
8963 {
8964 assert(!SCIPisInfinity(scip, -newlhs));
8965
8966 SCIP_CALL( chgLhs(scip, cons, newlhs) );
8967 if( !consdata->upgraded )
8968 (*nchgsides)++;
8969 }
8970 if( chgrhs )
8971 {
8972 assert(!SCIPisInfinity(scip, newrhs));
8973
8974 SCIP_CALL( chgRhs(scip, cons, newrhs) );
8975 if( !consdata->upgraded )
8976 (*nchgsides)++;
8977 }
8978 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8979 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8980 }
8981 }
8982
8983 return SCIP_OKAY;
8984}
8985
8986/** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
8987 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
8988 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
8989 * (i) ai >= 0:
8990 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
8991 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
8992 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8993 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8994 * - change coefficients:
8995 * ai' := max(lhs - minact, maxact - rhs, 0)
8996 * lhs' := lhs - (ai - ai')*li
8997 * rhs' := rhs - (ai - ai')*ui
8998 * (ii) ai < 0:
8999 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9000 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9001 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9002 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9003 * - change coefficients:
9004 * ai' := min(rhs - maxact, minact - lhs, 0)
9005 * lhs' := lhs - (ai - ai')*ui
9006 * rhs' := rhs - (ai - ai')*li
9007 *
9008 * We further try to remove variables from the constraint;
9009 * Variables which fulfill conditions (**) or (***) are called relevant variables.
9010 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9011 * variables are set to their "worst" bound. If all variables which are not relevant cannot make the lhs/rhs
9012 * redundant, even if they are set to their "best" bound, they can be removed from the constraint. E.g., for binary
9013 * variables and an inequality x_1 +x_2 +10y_1 +10y_2 >= 5, setting either of the y_i to one suffices to fulfill the
9014 * inequality, whereas the x_i do not contribute to feasibility and can be removed.
9015 *
9016 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9017 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9018 */
9019static
9021 SCIP* scip, /**< SCIP data structure */
9022 SCIP_CONS* cons, /**< linear constraint */
9023 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9024 int* nchgsides /**< pointer to count number of side changes */
9025 )
9026{
9027 SCIP_CONSDATA* consdata;
9028 SCIP_VAR* var;
9029 SCIP_Bool* isvarrelevant;
9030 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9031 * activity, ignoring the coefficients contributing with infinite value */
9032 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9033 * activity, ignoring the coefficients contributing with infinite value */
9034 SCIP_Bool isminacttight; /* are all contributions to the minactivity non-huge or non-contradicting? */
9035 SCIP_Bool ismaxacttight; /* are all contributions to the maxactivity non-huge or non-contradicting? */
9036 SCIP_Bool isminsettoinfinity;
9037 SCIP_Bool ismaxsettoinfinity;
9038 SCIP_Real minleftactivity; /* minimal activity without relevant variables */
9039 SCIP_Real maxleftactivity; /* maximal activity without relevant variables */
9040 SCIP_Real aggrlhs; /* lhs without minimal activity of relevant variables */
9041 SCIP_Real aggrrhs; /* rhs without maximal activity of relevant variables */
9042 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9043 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9044 SCIP_Real val;
9045 SCIP_Real newval;
9046 SCIP_Real newlhs;
9047 SCIP_Real newrhs;
9048 SCIP_Real lb;
9049 SCIP_Real ub;
9050 int i;
9051
9052 assert(scip != NULL);
9053 assert(cons != NULL);
9054 assert(nchgcoefs != NULL);
9055 assert(nchgsides != NULL);
9056
9057 consdata = SCIPconsGetData(cons);
9058 assert(consdata != NULL);
9059
9060 /* allocate relevance flags */
9061 SCIP_CALL( SCIPallocBufferArray(scip, &isvarrelevant, consdata->nvars) );
9062
9063 /* @todo Is this still needed with automatic recomputation of activities? */
9064 /* if the maximal coefficient is too large, recompute the activities */
9065 if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9066 || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9067 {
9070 }
9071
9072 /* get the minimal and maximal activity of the constraint */
9073 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9074 &isminsettoinfinity, &ismaxsettoinfinity);
9075 assert(( isminsettoinfinity && !SCIPisInfinity(scip, -consdata->lhs) )
9076 || SCIPisLT(scip, minactivity, consdata->lhs)
9077 || ( ismaxsettoinfinity && !SCIPisInfinity(scip, consdata->rhs) )
9078 || SCIPisGT(scip, maxactivity, consdata->rhs));
9079
9080 minleftactivity = 0.0;
9081 maxleftactivity = 0.0;
9082
9083 /* try to tighten each coefficient */
9084 i = 0;
9085 while( i < consdata->nvars )
9086 {
9087 /* get coefficient and variable's bounds */
9088 var = consdata->vars[i];
9089 val = consdata->vals[i];
9090 assert(!SCIPisZero(scip, val));
9091 lb = SCIPvarGetLbLocal(var);
9092 ub = SCIPvarGetUbLocal(var);
9093
9094 /* check sign of coefficient */
9095 if( val >= 0.0 )
9096 {
9097 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9098 isvarrelevant[i] = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS
9099 && SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs);
9100
9101 if( isvarrelevant[i] )
9102 {
9103 /* change coefficients:
9104 * ai' := max(lhs - minact, maxact - rhs)
9105 * lhs' := lhs - (ai - ai')*li
9106 * rhs' := rhs - (ai - ai')*ui
9107 */
9108
9109 lval = consdata->lhs - minactivity;
9110 rval = maxactivity - consdata->rhs;
9111
9112 /* Try to avoid cancellation, if there are only two variables */
9113 if( consdata->nvars == 2 )
9114 {
9115 SCIP_Real otherval;
9116 otherval = consdata->vals[1-i];
9117
9118 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9119 {
9120 lval = consdata->lhs - val*lb;
9121 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9122 }
9123
9124 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9125 {
9126 rval = val*ub - consdata->rhs;
9127 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9128 }
9129 }
9130
9131 newval = MAX3(lval, rval, 0.0);
9132 assert(SCIPisSumRelLE(scip, newval, val));
9133
9134 /* Try to avoid cancellation in computation of lhs/rhs */
9135 newlhs = consdata->lhs - val * lb;
9136 newlhs += newval * lb;
9137 newrhs = consdata->rhs - val * ub;
9138 newrhs += newval * ub;
9139
9140 if( !SCIPisSumRelEQ(scip, newval, val) )
9141 {
9142 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9143 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9144 maxactivity, consdata->lhs, consdata->rhs);
9145
9146 /* update the coefficient and the activity bounds */
9147 if( SCIPisZero(scip, newval) )
9148 {
9149 SCIP_CALL( delCoefPos(scip, cons, i) );
9150 --i;
9151 }
9152 else
9153 {
9154 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9155 }
9156 ++(*nchgcoefs);
9157
9158 /* get the new minimal and maximal activity of the constraint */
9159 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9160 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9161
9162 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9163 {
9164 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9165 consdata->lhs, newlhs);
9166
9167 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9168 (*nchgsides)++;
9169 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9170 }
9171
9172 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9173 {
9174 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9175 consdata->rhs, newrhs);
9176
9177 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9178 (*nchgsides)++;
9179 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9180 }
9181 }
9182 }
9183 else
9184 {
9185 if( !SCIPisInfinity(scip, -minleftactivity) )
9186 {
9187 assert(!SCIPisInfinity(scip, val));
9188 assert(!SCIPisInfinity(scip, lb));
9189 if( SCIPisInfinity(scip, -lb) )
9190 minleftactivity = -SCIPinfinity(scip);
9191 else
9192 minleftactivity += val * lb;
9193 }
9194
9195 if( !SCIPisInfinity(scip, maxleftactivity) )
9196 {
9197 assert(!SCIPisInfinity(scip, val));
9198 assert(!SCIPisInfinity(scip, -ub));
9199 if( SCIPisInfinity(scip,ub) )
9200 maxleftactivity = SCIPinfinity(scip);
9201 else
9202 maxleftactivity += val * ub;
9203 }
9204 }
9205 }
9206 else
9207 {
9208 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9209 isvarrelevant[i] = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS
9210 && SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs);
9211
9212 if( isvarrelevant[i] )
9213 {
9214 /* change coefficients:
9215 * ai' := min(rhs - maxact, minact - lhs)
9216 * lhs' := lhs - (ai - ai')*ui
9217 * rhs' := rhs - (ai - ai')*li
9218 */
9219
9220 lval = minactivity - consdata->lhs;
9221 rval = consdata->rhs - maxactivity;
9222
9223 /* Try to avoid cancellation, if there are only two variables */
9224 if( consdata->nvars == 2 )
9225 {
9226 SCIP_Real otherval;
9227 otherval = consdata->vals[1-i];
9228
9229 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9230 {
9231 lval = val*ub - consdata->lhs;
9232 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9233 }
9234
9235 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9236 {
9237 rval = consdata->rhs - val*lb;
9238 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9239 }
9240 }
9241
9242 newval = MIN3(lval, rval, 0.0);
9243 assert(SCIPisSumRelGE(scip, newval, val));
9244
9245 /* Try to avoid cancellation in computation of lhs/rhs */
9246 newlhs = consdata->lhs - val * ub;
9247 newlhs += newval * ub;
9248 newrhs = consdata->rhs - val * lb;
9249 newrhs += newval * lb;
9250
9251 if( !SCIPisSumRelEQ(scip, newval, val) )
9252 {
9253 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9254 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9255 maxactivity, consdata->lhs, consdata->rhs);
9256
9257 /* update the coefficient and the activity bounds */
9258 if( SCIPisZero(scip, newval) )
9259 {
9260 SCIP_CALL( delCoefPos(scip, cons, i) );
9261 --i;
9262 }
9263 else
9264 {
9265 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9266 }
9267 ++(*nchgcoefs);
9268
9269 /* get the new minimal and maximal activity of the constraint */
9270 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9271 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9272
9273 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9274 {
9275 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9276 consdata->lhs, newlhs);
9277
9278 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9279 (*nchgsides)++;
9280 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9281 }
9282
9283 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9284 {
9285 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9286 consdata->rhs, newrhs);
9287
9288 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9289 (*nchgsides)++;
9290 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9291 }
9292 }
9293 }
9294 else
9295 {
9296 if( !SCIPisInfinity(scip, -minleftactivity) )
9297 {
9298 assert(!SCIPisInfinity(scip, -val));
9299 assert(!SCIPisInfinity(scip, -ub));
9300 if( SCIPisInfinity(scip, ub) )
9301 minleftactivity = -SCIPinfinity(scip);
9302 else
9303 minleftactivity += val * ub;
9304 }
9305
9306 if( !SCIPisInfinity(scip, maxleftactivity) )
9307 {
9308 assert(!SCIPisInfinity(scip, -val));
9309 assert(!SCIPisInfinity(scip, lb));
9310 if( SCIPisInfinity(scip, -lb) )
9311 maxleftactivity = SCIPinfinity(scip);
9312 else
9313 maxleftactivity += val * lb;
9314 }
9315 }
9316 }
9317
9318 ++i;
9319 }
9320
9321 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9322 minleftactivity, consdata->rhs);
9323 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9324 maxleftactivity, consdata->lhs);
9325
9326 /* minleft == \infty ==> minactivity == \infty */
9327 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9328 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9329
9330 /* if the lhs is finite, we will check in the following whether the not relevant variables can make lhs feasible;
9331 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9332 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9333 * (<= the exact minactivity), and we might falsely remove coefficients in the following
9334 */
9335 assert(!SCIPisInfinity(scip, minactivity));
9336 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
9337 goto TERMINATE;
9338
9339 /* if the rhs is finite, we will check in the following whether the not relevant variables can make rhs feasible;
9340 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9341 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9342 * (>= the exact maxactivity), and we might falsely remove coefficients in the following
9343 */
9344 assert(!SCIPisInfinity(scip, -maxactivity));
9345 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
9346 goto TERMINATE;
9347
9348 /* correct lhs and rhs by min/max activity of relevant variables
9349 * relevant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9350 */
9351 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9352 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9353
9354 /* check if the constraint contains variables whose coefficient can be removed. The reasoning is the following:
9355 * Each relevant variable can make the lhs/rhs feasible with a deviation of only one in the bound. If _all_ not
9356 * relevant variables together cannot make lhs/rhs redundant, they can be removed from the constraint. aggrrhs may
9357 * contain some near-infinity value, but only if rhs is infinity.
9358 */
9359 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9360 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9361 {
9362 SCIP_Real minleftactivitypart;
9363 SCIP_Real maxleftactivitypart;
9364
9365 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9366
9367 /* remove redundant variables from constraint */
9368 i = 0;
9369 while( i < consdata->nvars )
9370 {
9371 /* consider redundant variable */
9372 if( !isvarrelevant[i] )
9373 {
9374 /* get coefficient and variable's bounds */
9375 var = consdata->vars[i];
9376 val = consdata->vals[i];
9377 assert(!SCIPisZero(scip, val));
9378 lb = SCIPvarGetLbLocal(var);
9379 ub = SCIPvarGetUbLocal(var);
9380
9381 SCIPdebugMsg(scip, "val = %g\tlhs = %g\trhs = %g\n", val, consdata->lhs, consdata->rhs);
9382 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> from constraint since it is redundant\n",
9383 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
9384
9385 /* check sign of coefficient */
9386 if( val >= 0.0 )
9387 {
9388 minleftactivitypart = val * lb;
9389 maxleftactivitypart = val * ub;
9390 }
9391 else
9392 {
9393 minleftactivitypart = val * ub;
9394 maxleftactivitypart = val * lb;
9395 }
9396
9397 /* remove redundant variable */
9398 isvarrelevant[i] = isvarrelevant[consdata->nvars - 1];
9399 SCIP_CALL( delCoefPos(scip, cons, i) );
9400 --i;
9401
9402 /* adjust lhs and right hand side */
9403 newlhs = consdata->lhs - minleftactivitypart;
9404 newrhs = consdata->rhs - maxleftactivitypart;
9405
9406 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9407 {
9408 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9409 consdata->lhs, newlhs);
9410
9411 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9412 ++(*nchgsides);
9413 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9414 }
9415
9416 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9417 {
9418 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9419 consdata->rhs, newrhs);
9420
9421 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9422 ++(*nchgsides);
9423 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9424 }
9425 }
9426
9427 ++i;
9428 }
9429 }
9430
9431TERMINATE:
9432 /* free relevance flags */
9433 SCIPfreeBufferArray(scip, &isvarrelevant);
9434
9435 return SCIP_OKAY;
9436}
9437
9438/** processes equality with only one variable by fixing the variable and deleting the constraint */
9439static
9441 SCIP* scip, /**< SCIP data structure */
9442 SCIP_CONS* cons, /**< linear constraint */
9443 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9444 int* nfixedvars, /**< pointer to count number of fixed variables */
9445 int* ndelconss /**< pointer to count number of deleted constraints */
9446 )
9447{
9448 SCIP_CONSDATA* consdata;
9449 SCIP_VAR* var;
9450 SCIP_Real val;
9451 SCIP_Real fixval;
9452 SCIP_Bool infeasible;
9453 SCIP_Bool fixed;
9454
9455 assert(scip != NULL);
9456 assert(cons != NULL);
9457 assert(cutoff != NULL);
9458 assert(nfixedvars != NULL);
9459 assert(ndelconss != NULL);
9460
9461 consdata = SCIPconsGetData(cons);
9462 assert(consdata != NULL);
9463 assert(consdata->nvars == 1);
9464 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9465
9466 /* calculate the value to fix the variable to */
9467 var = consdata->vars[0];
9468 val = consdata->vals[0];
9469 assert(!SCIPisZero(scip, val));
9470 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9471 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9472 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9473 SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9474
9475 /* fix variable */
9476 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9477 if( infeasible )
9478 {
9479 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9480 *cutoff = TRUE;
9481 return SCIP_OKAY;
9482 }
9483 if( fixed )
9484 (*nfixedvars)++;
9485
9486 /* disable constraint */
9487 SCIP_CALL( SCIPdelCons(scip, cons) );
9488 if( !consdata->upgraded )
9489 (*ndelconss)++;
9490
9491 return SCIP_OKAY;
9492}
9493
9494/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9495static
9497 SCIP* scip, /**< SCIP data structure */
9498 SCIP_CONS* cons, /**< linear constraint */
9499 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9500 int* naggrvars, /**< pointer to count number of aggregated variables */
9501 int* ndelconss /**< pointer to count number of deleted constraints */
9502 )
9503{
9504 SCIP_CONSDATA* consdata;
9505 SCIP_Bool infeasible;
9506 SCIP_Bool redundant;
9507 SCIP_Bool aggregated;
9508
9509 assert(scip != NULL);
9510 assert(cons != NULL);
9511 assert(cutoff != NULL);
9512 assert(naggrvars != NULL);
9513 assert(ndelconss != NULL);
9514
9515 consdata = SCIPconsGetData(cons);
9516 assert(consdata != NULL);
9517 assert(consdata->nvars == 2);
9518 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9519
9520 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9521 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9522 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9523
9524 /* aggregate the equality */
9525 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9526 consdata->rhs, &infeasible, &redundant, &aggregated) );
9527
9528 /* check for infeasibility of aggregation */
9529 if( infeasible )
9530 {
9531 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9532 *cutoff = TRUE;
9533 return SCIP_OKAY;
9534 }
9535
9536 /* count the aggregation */
9537 if( aggregated )
9538 (*naggrvars)++;
9539
9540 /* delete the constraint, if it is redundant */
9541 if( redundant )
9542 {
9543 SCIP_CALL( SCIPdelCons(scip, cons) );
9544
9545 if( !consdata->upgraded )
9546 (*ndelconss)++;
9547 }
9548
9549 return SCIP_OKAY;
9550}
9551
9552/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9553static
9555 SCIP* scip, /**< SCIP data structure */
9556 SCIP_CONSDATA* consdata, /**< linear constraint data */
9557 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9558 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9559 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9560 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9561 )
9562{
9563 SCIP_Real slackvarlb;
9564 SCIP_Real slackvarub;
9565
9566 assert(scip != NULL);
9567 assert(consdata != NULL);
9568 assert(newlhs != NULL);
9569 assert(newrhs != NULL);
9570 assert(!SCIPisInfinity(scip, -consdata->lhs));
9571 assert(!SCIPisInfinity(scip, consdata->rhs));
9572
9573 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9574 slackvarub = SCIPvarGetUbGlobal(slackvar);
9575 if( slackcoef > 0.0 )
9576 {
9577 if( SCIPisInfinity(scip, -slackvarlb) )
9578 *newrhs = SCIPinfinity(scip);
9579 else
9580 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9581 if( SCIPisInfinity(scip, slackvarub) )
9582 *newlhs = -SCIPinfinity(scip);
9583 else
9584 *newlhs = consdata->lhs - slackcoef * slackvarub;
9585 }
9586 else
9587 {
9588 if( SCIPisInfinity(scip, -slackvarlb) )
9589 *newlhs = -SCIPinfinity(scip);
9590 else
9591 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9592 if( SCIPisInfinity(scip, slackvarub) )
9593 *newrhs = SCIPinfinity(scip);
9594 else
9595 *newrhs = consdata->lhs - slackcoef * slackvarub;
9596 }
9597 assert(SCIPisLE(scip, *newlhs, *newrhs));
9598}
9599
9600/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9601 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9602 * is implicitly integral by this constraint
9603 *
9604 * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9605 * can help.
9606 */
9607static
9609 SCIP* scip, /**< SCIP data structure */
9610 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9611 SCIP_CONS* cons, /**< linear constraint */
9612 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9613 int* naggrvars, /**< pointer to count number of aggregated variables */
9614 int* ndelconss, /**< pointer to count number of deleted constraints */
9615 int* nchgvartypes /**< pointer to count number of changed variable types */
9616 )
9617{
9618 SCIP_CONSDATA* consdata;
9619 SCIP_VAR** vars;
9620 SCIP_Real* vals;
9621 SCIP_VARTYPE bestslacktype;
9622 SCIP_VARTYPE slacktype;
9623 SCIP_Real lhs;
9624 SCIP_Real rhs;
9625 SCIP_Real bestslackdomrng;
9626 SCIP_Real minabsval;
9627 SCIP_Real maxabsval;
9628 SCIP_Bool bestremovescons;
9629 SCIP_Bool coefszeroone;
9630 SCIP_Bool coefsintegral;
9631 SCIP_Bool varsintegral;
9632 SCIP_Bool infeasible;
9633 SCIP_Bool samevar;
9634 int supinf; /* counter for infinite contributions to the supremum of a possible
9635 * multi-aggregation
9636 */
9637 int infinf; /* counter for infinite contributions to the infimum of a possible
9638 * multi-aggregation
9639 */
9640 int maxnlocksstay;
9641 int maxnlocksremove;
9642 int bestslackpos;
9643 int bestnlocks;
9644 int ncontvars;
9645 int contvarpos;
9646 int nintvars;
9647 int nimplvars;
9648 int intvarpos;
9649 int v;
9650
9651 assert(scip != NULL);
9652 assert(cons != NULL);
9653 assert(cutoff != NULL);
9654 assert(naggrvars != NULL);
9655
9656 consdata = SCIPconsGetData(cons);
9657 assert(consdata != NULL);
9658 assert(consdata->nvars > 2);
9659 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9660
9661 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9662
9663 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9664 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9665 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9666 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9667 */
9668 lhs = consdata->lhs;
9669 rhs = consdata->rhs;
9670 maxnlocksstay = 0;
9671 if( consdata->nvars == 3 )
9672 {
9673 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9674 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9675 */
9676 maxnlocksremove = 3;
9677 }
9678 else if( consdata->nvars == 4 )
9679 {
9680 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9681 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9682 */
9683 maxnlocksremove = 2;
9684 }
9685 else
9686 {
9687 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9688 maxnlocksremove = 1;
9689 }
9690
9691 /* the locks on this constraint can be ignored */
9692 if( SCIPconsIsChecked(cons) )
9693 {
9694 if( !SCIPisInfinity(scip, -lhs) )
9695 {
9696 maxnlocksstay++;
9697 maxnlocksremove++;
9698 }
9699 if( !SCIPisInfinity(scip, rhs) )
9700 {
9701 maxnlocksstay++;
9702 maxnlocksremove++;
9703 }
9704 }
9705
9706 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9707 vars = consdata->vars;
9708 vals = consdata->vals;
9709 bestslackpos = -1;
9710 bestslacktype = SCIP_VARTYPE_BINARY;
9711 bestnlocks = INT_MAX;
9712 bestremovescons = FALSE;
9713 bestslackdomrng = 0.0;
9714 coefszeroone = TRUE;
9715 coefsintegral = TRUE;
9716 varsintegral = TRUE;
9717 ncontvars = 0;
9718 contvarpos = -1;
9719 nintvars = 0;
9720 nimplvars = 0;
9721 intvarpos = -1;
9722 minabsval = SCIPinfinity(scip);
9723 maxabsval = -1.0;
9724 for( v = 0; v < consdata->nvars; ++v )
9725 {
9726 SCIP_VAR* var;
9727 SCIP_Real val;
9728 SCIP_Real absval;
9729 SCIP_Real varlb;
9730 SCIP_Real varub;
9731 SCIP_Bool iscont;
9732 int nlocks;
9733
9734 assert(vars != NULL);
9735 assert(vals != NULL);
9736
9737 var = vars[v];
9738 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9740 varlb = SCIPvarGetLbGlobal(var);
9741 varub = SCIPvarGetUbGlobal(var);
9742
9743 val = vals[v];
9744 absval = REALABS(val);
9745 assert(SCIPisPositive(scip, absval));
9746
9747 /* calculate minimal and maximal absolute value */
9748 if( absval < minabsval )
9749 minabsval = absval;
9750 if( absval > maxabsval )
9751 maxabsval = absval;
9752
9753 /*TODO: why exit here when implied integrality can still be derived?!*/
9754 /* do not try to multi aggregate, when numerical bad */
9755 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9756 return SCIP_OKAY;
9757
9758 slacktype = SCIPvarGetType(var);
9759 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9760 coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9761 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9762 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9763
9764 /* update candidates for continuous -> implint and integer -> implint conversion */
9765 if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9766 {
9767 ncontvars++;
9768 contvarpos = v;
9769 }
9770 else if( slacktype == SCIP_VARTYPE_IMPLINT )
9771 {
9772 ++nimplvars;
9773 }
9774 else if( slacktype == SCIP_VARTYPE_INTEGER )
9775 {
9776 nintvars++;
9777 intvarpos = v;
9778 }
9779
9780 /* check, if variable is already fixed or aggregated */
9781 if( !SCIPvarIsActive(var) )
9782 continue;
9783
9784 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9786
9787 if( nlocks > maxnlocksremove )
9788 continue;
9789
9790 /* check, if variable can be used as a slack variable */
9791 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9792 !SCIPdoNotMultaggrVar(scip, var) )
9793 {
9794 SCIP_Bool better;
9795 SCIP_Bool equal;
9796 SCIP_Real slackdomrng;
9797
9798 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9799 slackdomrng = SCIPinfinity(scip);
9800 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9801 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9802 return SCIP_OKAY;
9803 else
9804 {
9805 slackdomrng = (varub - varlb)*absval;
9806 assert(!SCIPisInfinity(scip, slackdomrng));
9807 }
9808 equal = FALSE;
9809 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9810 if( !better && slacktype == bestslacktype )
9811 {
9812 better = (nlocks < bestnlocks);
9813 if( nlocks == bestnlocks && !bestremovescons )
9814 {
9815 better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9816 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9817 }
9818 }
9819
9820 if( better || equal )
9821 {
9822 SCIP_Real minresactivity;
9823 SCIP_Real maxresactivity;
9824 SCIP_Real newlhs;
9825 SCIP_Real newrhs;
9826 SCIP_Bool removescons;
9827 SCIP_Bool ismintight;
9828 SCIP_Bool ismaxtight;
9829 SCIP_Bool isminsettoinfinity;
9830 SCIP_Bool ismaxsettoinfinity;
9831
9832 /* check if the constraint becomes redundant after multi-aggregation */
9833 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9834 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
9835
9836 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9837 * activity
9838 */
9839 if( !ismintight || !ismaxtight )
9840 continue;
9841
9842 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9843 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9844
9845 /* check resactivities for reliability */
9846 if( removescons )
9847 {
9848 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9849 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9850
9851 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9852 && SCIPisFeasLE(scip, newlhs, minresactivity))
9853 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9854
9855 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9856 }
9857
9858 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9859 if( conshdlrdata->multaggrremove && !removescons )
9860 continue;
9861
9862 /* prefer variables that make the constraints redundant */
9863 if( bestremovescons && !removescons )
9864 continue;
9865
9866 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9867 * other constraints
9868 */
9869 if( !removescons && nlocks > maxnlocksstay )
9870 continue;
9871
9872 better = better || (!bestremovescons && removescons);
9873 if( better )
9874 {
9875 bestslackpos = v;
9876 bestslacktype = slacktype;
9877 bestnlocks = nlocks;
9878 bestslackdomrng = slackdomrng;
9879 bestremovescons = removescons;
9880 }
9881 }
9882 }
9883 }
9884
9885 /* if all coefficients and variables are integral, the right hand side must also be integral */
9886 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9887 {
9888 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9890 *cutoff = TRUE;
9891 return SCIP_OKAY;
9892 }
9893
9894 supinf = 0;
9895 infinf = 0;
9896 samevar = FALSE;
9897
9898 /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9899 for( v = 0; v < consdata->nvars; ++v )
9900 {
9901 if( v != bestslackpos )
9902 {
9903 if( SCIPisPositive(scip, consdata->vals[v]) )
9904 {
9905 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9906 {
9907 ++supinf;
9908 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9909 {
9910 ++infinf;
9911 samevar = TRUE;
9912 }
9913 }
9914 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9915 ++infinf;
9916 }
9917 else if( SCIPisNegative(scip, consdata->vals[v]) )
9918 {
9919 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9920 {
9921 ++supinf;
9922 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9923 {
9924 ++infinf;
9925 samevar = TRUE;
9926 }
9927 }
9928 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9929 ++infinf;
9930 }
9931 }
9932 }
9933 assert(!samevar || (supinf > 0 && infinf > 0));
9934
9935 /*TODO: implint detection again terminates early here*/
9936 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9937 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9938 if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9939 {
9940 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9941 return SCIP_OKAY;
9942 }
9943
9944 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9945 * we cannot aggregate the variable, because the integrality condition would get lost
9946 * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9947 * loose the integrality condition for this variable.
9948 */
9949 if( bestslackpos >= 0
9950 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9951 || (coefsintegral && varsintegral && nimplvars == 0)) )
9952 {
9953 SCIP_VAR* slackvar;
9955 SCIP_Real slackcoef;
9956 SCIP_Real aggrconst;
9957 SCIP_Real newlhs;
9958 SCIP_Real newrhs;
9959 SCIP_Bool aggregated;
9960
9961 /* we found a slack variable that only occurs in at most one other constraint:
9962 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9963 */
9964 assert(bestslackpos < consdata->nvars);
9965
9966 /* do not multi aggregate binary variables */
9967 if( SCIPvarIsBinary(vars[bestslackpos]) )
9968 return SCIP_OKAY;
9969
9970 /* convert equality into inequality by deleting the slack variable:
9971 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9972 */
9973 slackvar = vars[bestslackpos];
9974 slackcoef = vals[bestslackpos];
9975 assert(!SCIPisZero(scip, slackcoef));
9976 aggrconst = consdata->rhs/slackcoef;
9977
9978 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9979 assert(SCIPisLE(scip, newlhs, newrhs));
9980 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9981 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9982 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9983
9984 /* allocate temporary memory */
9985 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
9986
9987 /* set up the multi-aggregation */
9988 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9989 for( v = 0; v < consdata->nvars; ++v )
9990 {
9991 scalars[v] = -consdata->vals[v]/slackcoef;
9992 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
9993 }
9994 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9995 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9996 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9997
9998 /* perform the multi-aggregation */
9999 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10000 &infeasible, &aggregated) );
10001 assert(aggregated);
10002
10003 /* free temporary memory */
10005
10006 /* check for infeasible aggregation */
10007 if( infeasible )
10008 {
10009 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10010 *cutoff = TRUE;
10011 return SCIP_OKAY;
10012 }
10013
10014 (*naggrvars)++;
10015
10016 /* delete the constraint if it became redundant */
10017 if( bestremovescons )
10018 {
10019 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10020 SCIP_CALL( SCIPdelCons(scip, cons) );
10021
10022 if( !consdata->upgraded )
10023 (*ndelconss)++;
10024 }
10025 }
10026 else if( ncontvars == 1 )
10027 {
10028 SCIP_VAR* var;
10029
10030 assert(0 <= contvarpos && contvarpos < consdata->nvars);
10031 var = vars[contvarpos];
10033
10034 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10035 {
10036 /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10037 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10038 {
10039 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10040 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10041 SCIPconsGetName(cons), SCIPvarGetName(var));
10042 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10043 (*nchgvartypes)++;
10044 if( infeasible )
10045 {
10046 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10047 *cutoff = TRUE;
10048
10049 return SCIP_OKAY;
10050 }
10051 }
10052 /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10053 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10054 else if( !SCIPdoNotAggr(scip) )
10055 {
10056 SCIP_VAR* newvar;
10057 SCIP_Real absval;
10058 char newvarname[SCIP_MAXSTRLEN];
10059 SCIP_Bool redundant;
10060 SCIP_Bool aggregated;
10061
10062 absval = REALABS(vals[contvarpos]);
10063
10064 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10065
10066 /* create new implicit variable for aggregation */
10067 SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10069
10070 /* add new variable to problem */
10071 SCIP_CALL( SCIPaddVar(scip, newvar) );
10072
10073#ifdef WITH_DEBUG_SOLUTION
10074 if( SCIPdebugIsMainscip(scip) )
10075 {
10076 SCIP_Real varval;
10077 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10078 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10079 }
10080#endif
10081
10082 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10083 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10084 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10085
10086 /* aggregate continuous and implicit variable */
10087 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10088
10089 if( infeasible )
10090 {
10091 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10092 SCIPvarGetName(var), SCIPvarGetName(newvar));
10093 *cutoff = TRUE;
10094
10095 /* release implicit variable */
10096 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10097
10098 return SCIP_OKAY;
10099 }
10100
10101 /* release implicit variable */
10102 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10103
10104 if( aggregated )
10105 (*naggrvars)++;
10106 else
10107 return SCIP_OKAY;
10108 }
10109
10110 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10111 * again
10112 */
10113 consdata->boundstightened = 0;
10114 consdata->rangedrowpropagated = 0;
10115 consdata->presolved = FALSE;
10116 }
10117 }
10118 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10119 {
10120 SCIP_VAR* var;
10121
10122 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10123 * -> we don't convert integers into implints if the row is a 0/1-row
10124 */
10125 assert(varsintegral);
10126 assert(0 <= intvarpos && intvarpos < consdata->nvars);
10127 var = vars[intvarpos];
10128 assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10129
10130 if( coefsintegral
10131 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10132 && SCIPisFeasIntegral(scip, consdata->rhs) )
10133 {
10134 /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10135 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10136 SCIPconsGetName(cons), SCIPvarGetName(var));
10137 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10138 (*nchgvartypes)++;
10139 if( infeasible )
10140 {
10141 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10142 *cutoff = TRUE;
10143
10144 return SCIP_OKAY;
10145 }
10146 }
10147 }
10148
10149 return SCIP_OKAY;
10150}
10151
10152/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10153static
10155 SCIP* scip, /**< SCIP data structure */
10156 SCIP_CONSDATA* consdata, /**< linear constraint data */
10157 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10158 * objective function */
10159 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10160 * this constraint */
10161 )
10162{
10163 SCIP_VAR** vars;
10164 SCIP_VAR* var;
10165 SCIP_Real objval;
10166 SCIP_Bool negated;
10167 int nvars;
10168 int v;
10169
10170 vars = consdata->vars;
10171 nvars = consdata->nvars;
10172
10173 assert(vars != NULL);
10174
10175 for( v = 0; v < nvars; ++v )
10176 {
10177 negated = FALSE;
10178 var = vars[v];
10179 assert(var != NULL);
10180
10181 if( SCIPvarIsNegated(var) )
10182 {
10183 negated = TRUE;
10184 var = SCIPvarGetNegatedVar(var);
10185 assert(var != NULL);
10186 }
10187
10188 objval = SCIPvarGetObj(var);
10189
10190 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10191 * function
10192 */
10193 if( SCIPisZero(scip, objval) )
10194 return FALSE;
10195 else
10196 {
10197 SCIP_Real val;
10198
10199 val = consdata->vals[v];
10200
10201 if( negated )
10202 {
10203 if( v == 0 )
10204 {
10205 /* the first variable defines the scale */
10206 (*scale) = val / -objval;
10207
10208 (*offset) += val;
10209 }
10210 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10211 (*offset) += val;
10212 else
10213 return FALSE;
10214 }
10215 else if( v == 0 )
10216 {
10217 /* the first variable defines the scale */
10218 (*scale) = val / objval;
10219 }
10220 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10221 return FALSE;
10222 }
10223 }
10224
10225 return TRUE;
10226}
10227
10228/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10229 * objective coefficients and add an objective offset
10230 */
10231static
10233 SCIP* scip, /**< SCIP data structure */
10234 SCIP_CONS* cons, /**< linear equation constraint */
10235 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10236 )
10237{
10238 SCIP_CONSDATA* consdata;
10239 SCIP_Real offset;
10240 SCIP_Real scale;
10241 SCIP_Bool applicable;
10242 int nobjvars;
10243 int nvars;
10244 int v;
10245
10246 assert(scip != NULL);
10247 assert(cons != NULL);
10248 assert(conshdlrdata != NULL);
10249
10250 consdata = SCIPconsGetData(cons);
10251 assert(consdata != NULL);
10252 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10253
10254 nvars = consdata->nvars;
10255 nobjvars = SCIPgetNObjVars(scip);
10256
10257 /* check if the linear equality constraints does not have more variables than the objective function */
10258 if( nvars > nobjvars || nvars == 0 )
10259 return SCIP_OKAY;
10260
10261 /* check for allowance of algorithm */
10262 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10263 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10264 return SCIP_OKAY;
10265
10266 offset = consdata->rhs;
10267 scale = 1.0;
10268
10269 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10270 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10271
10272 if( applicable )
10273 {
10274 SCIP_VAR** vars;
10275
10276 vars = consdata->vars;
10277 assert(vars != NULL);
10278
10279 offset /= scale;
10280
10281 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10282 SCIPconsGetName(cons), consdata->rhs, offset);
10283
10284 /* make equality a model constraint to ensure optimality in this direction */
10287
10288 /* set all objective coefficient to zero */
10289 for( v = 0; v < nvars; ++v )
10290 {
10291 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10292 }
10293
10294 /* add an objective offset */
10295 SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10296 }
10297
10298 return SCIP_OKAY;
10299}
10300
10301/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10302static
10304 SCIP* scip, /**< SCIP data structure */
10305 SCIP_CONS* cons, /**< constraint */
10306 SCIP_Real primalbound /**< feasible primal bound */
10307 )
10308{
10309 SCIP_Real cutoffbound;
10310
10311 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10312 * accepted
10313 */
10314 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10315
10316 if( cutoffbound < SCIPgetCutoffbound(scip) )
10317 {
10318 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10319
10320 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10321 }
10322 else
10323 {
10324 SCIP_CONSDATA* consdata;
10325
10326 consdata = SCIPconsGetData(cons);
10327 assert(consdata != NULL);
10328
10329 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10330 * resulted from one side
10331 */
10332 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10333 {
10334 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10335 * propagation
10336 */
10339 }
10340 }
10341
10342 return SCIP_OKAY;
10343}
10344
10345/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10346 * constraint enters the LP by setting the initial and separated flag to FALSE
10347 */
10348static
10350 SCIP* scip, /**< SCIP data structure */
10351 SCIP_CONS* cons, /**< linear constraint */
10352 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10353 )
10354{
10355 SCIP_CONSDATA* consdata;
10356 SCIP_Real offset;
10357 SCIP_Real scale;
10358 SCIP_Bool applicable;
10359 int nobjvars;
10360 int nvars;
10361
10362 assert(scip != NULL);
10363 assert(cons != NULL);
10364 assert(conshdlrdata != NULL);
10365
10366 consdata = SCIPconsGetData(cons);
10367 assert(consdata != NULL);
10368
10369 /* ignore equalities since these are covered by the method checkPartialObjective() */
10370 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10371 return SCIP_OKAY;
10372
10373 nvars = consdata->nvars;
10374 nobjvars = SCIPgetNObjVars(scip);
10375
10376 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10377 * initial and/or separated flag is set to FALSE
10378 */
10379 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10380 return SCIP_OKAY;
10381
10382 offset = 0.0;
10383 scale = 1.0;
10384
10385 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10386 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10387 */
10388 if( nobjvars == 0 )
10389 return SCIP_OKAY;
10390
10391 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10392 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10393
10394 if( applicable )
10395 {
10396 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10397 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10398
10399 assert(scale != 0.0);
10400
10401 if( scale > 0.0 )
10402 {
10403 if( conshdlrdata->detectcutoffbound && rhsfinite )
10404 {
10405 SCIP_Real primalbound;
10406
10407 primalbound = (consdata->rhs - offset) / scale;
10408
10409 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10410 SCIPconsGetName(cons), primalbound);
10411
10412 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10413 }
10414
10415 if( conshdlrdata->detectlowerbound && lhsfinite )
10416 {
10417 SCIP_Real lowerbound;
10418
10419 lowerbound = (consdata->lhs - offset) / scale;
10420
10421 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10422 SCIPconsGetName(cons), lowerbound);
10423
10425 }
10426
10427 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10428 (conshdlrdata->detectlowerbound && !rhsfinite) )
10429 {
10430 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10433 }
10434 }
10435 else
10436 {
10437 if( conshdlrdata->detectlowerbound && rhsfinite )
10438 {
10439 SCIP_Real lowerbound;
10440
10441 lowerbound = (consdata->rhs - offset) / scale;
10442
10443 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10444 SCIPconsGetName(cons), lowerbound);
10445
10447 }
10448
10449 if( conshdlrdata->detectcutoffbound && lhsfinite )
10450 {
10451 SCIP_Real primalbound;
10452
10453 primalbound = (consdata->lhs - offset) / scale;
10454
10455 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10456 SCIPconsGetName(cons), primalbound);
10457
10458 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10459 }
10460
10461 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10462 (conshdlrdata->detectlowerbound && !lhsfinite) )
10463 {
10464 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10467 }
10468 }
10469 }
10470
10471 return SCIP_OKAY;
10472}
10473
10474/** converts special equalities */
10475static
10477 SCIP* scip, /**< SCIP data structure */
10478 SCIP_CONS* cons, /**< linear constraint */
10479 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10480 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10481 int* nfixedvars, /**< pointer to count number of fixed variables */
10482 int* naggrvars, /**< pointer to count number of aggregated variables */
10483 int* ndelconss, /**< pointer to count number of deleted constraints */
10484 int* nchgvartypes /**< pointer to count number of changed variable types */
10485 )
10486{
10487 SCIP_CONSDATA* consdata;
10488
10489 assert(scip != NULL);
10490 assert(cons != NULL);
10491 assert(conshdlrdata != NULL);
10492 assert(cutoff != NULL);
10493 assert(nfixedvars != NULL);
10494 assert(naggrvars != NULL);
10495 assert(ndelconss != NULL);
10496
10497 consdata = SCIPconsGetData(cons);
10498 assert(consdata != NULL);
10499 assert(consdata->removedfixings);
10500
10501 /* do nothing on inequalities */
10502 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10503 return SCIP_OKAY;
10504
10505 /* depending on the number of variables, call a special conversion method */
10506 if( consdata->nvars == 1 )
10507 {
10508 /* fix variable */
10509 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10510 }
10511 else if( consdata->nvars == 2 )
10512 {
10513 /* aggregate one of the variables */
10514 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10515 }
10516 else
10517 {
10518 /* check if the equality is part of the objective function */
10519 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10520
10521 /* try to multi-aggregate one of the variables */
10522 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss, nchgvartypes) );
10523 }
10524
10525 return SCIP_OKAY;
10526}
10527
10528/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10529 * integral
10530 */
10531static
10533 SCIP* scip, /**< SCIP data structure */
10534 SCIP_CONSDATA* consdata, /**< linear constraint */
10535 int pos, /**< position of variable to be left out */
10536 SCIP_Real val /**< value to divide the coefficients by */
10537 )
10538{
10539 int v;
10540
10541 assert(scip != NULL);
10542 assert(consdata != NULL);
10543 assert(0 <= pos && pos < consdata->nvars);
10544
10545 for( v = 0; v < consdata->nvars; ++v )
10546 {
10547 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10548 return FALSE;
10549 }
10550
10551 return TRUE;
10552}
10553
10554/** 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$,
10555 * 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$
10556 */
10557static
10559 SCIP* scip, /**< SCIP data structure */
10560 SCIP_Real side, /**< lhs or rhs */
10561 SCIP_Real val, /**< coefficient */
10562 SCIP_Real minresactivity, /**< minimal residual activity */
10563 SCIP_Real maxresactivity, /**< maximal residual activity */
10564 SCIP_Real* minval, /**< pointer to store calculated minval */
10565 SCIP_Real* maxval /**< pointer to store calculated maxval */
10566 )
10567{
10568 assert(scip != NULL);
10569 assert(minval != NULL);
10570 assert(maxval != NULL);
10571
10572 if( val > 0.0 )
10573 {
10574 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10575 *minval = -maxresactivity;
10576 else
10577 *minval = (side - maxresactivity)/val;
10578
10579 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10580 *maxval = -minresactivity;
10581 else
10582 *maxval = (side - minresactivity)/val;
10583 }
10584 else
10585 {
10586 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10587 *minval = minresactivity;
10588 else
10589 *minval = (side - minresactivity)/val;
10590
10591 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10592 *maxval = maxresactivity;
10593 else
10594 *maxval = (side - maxresactivity)/val;
10595 }
10596}
10597
10598
10599/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10600 * linear inequality
10601 */
10602static
10604 SCIP* scip, /**< SCIP data structure */
10605 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10606 SCIP_CONS* cons, /**< linear constraint */
10607 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10608 int* nfixedvars, /**< pointer to count number of fixed variables */
10609 int* naggrvars, /**< pointer to count number of aggregated variables */
10610 int* ndelconss, /**< pointer to count number of deleted constraints */
10611 int* nchgvartypes /**< pointer to count number of changed variable types */
10612 )
10613{
10614 SCIP_CONSDATA* consdata;
10615 SCIP_Bool lhsexists;
10616 SCIP_Bool rhsexists;
10617 SCIP_Bool bestisint;
10618 SCIP_Bool bestislhs;
10619 SCIP_Real minabsval;
10620 SCIP_Real maxabsval;
10621 int bestpos;
10622 int i;
10623 int maxotherlocks;
10624
10625 assert(scip != NULL);
10626 assert(cons != NULL);
10627 assert(cutoff != NULL);
10628 assert(nfixedvars != NULL);
10629 assert(naggrvars != NULL);
10630 assert(ndelconss != NULL);
10631
10632 /* only process checked constraints (for which the locks are increased);
10633 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10634 * dualfix presolver
10635 */
10636 if( !SCIPconsIsChecked(cons) )
10637 return SCIP_OKAY;
10638
10639 consdata = SCIPconsGetData(cons);
10640 assert(consdata != NULL);
10641
10642 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10643 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10644
10645 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10646 * can use it safely for aggregation and break the search loop
10647 */
10648 bestpos = -1;
10649 bestisint = TRUE;
10650 bestislhs = FALSE;
10651
10652 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10653 * everything else would produce fill-in. Exceptions:
10654 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10655 * produced.
10656 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10657 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10658 * six nonzeros (two variables per substitution).
10659 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10660 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10661 * six nonzeros (three variables per substitution). God exists!
10662 */
10663 if( consdata->nvars <= 2 )
10664 maxotherlocks = INT_MAX;
10665 else if( consdata->nvars == 3 )
10666 maxotherlocks = 3;
10667 else if( consdata->nvars == 4 )
10668 maxotherlocks = 2;
10669 else
10670 maxotherlocks = 1;
10671
10672 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10673 if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10674 maxotherlocks++;
10675
10676 minabsval = SCIPinfinity(scip);
10677 maxabsval = -1.0;
10678 for( i = 0; i < consdata->nvars && bestisint; ++i )
10679 {
10680 SCIP_VAR* var;
10681 SCIP_Bool isint;
10682 SCIP_Real val;
10683 SCIP_Real absval;
10684 SCIP_Real obj;
10685 SCIP_Real lb;
10686 SCIP_Real ub;
10687 SCIP_Bool agglhs;
10688 SCIP_Bool aggrhs;
10689
10690 val = consdata->vals[i];
10691 absval = REALABS(val);
10692
10693 /* calculate minimal and maximal absolute value */
10694 if( absval < minabsval )
10695 minabsval = absval;
10696 if( absval > maxabsval )
10697 maxabsval = absval;
10698
10699 /* do not try to multi aggregate, when numerical bad */
10700 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10701 return SCIP_OKAY;
10702
10703 var = consdata->vars[i];
10705
10706 /* if we already found a candidate, skip integers */
10707 if( bestpos >= 0 && isint )
10708 continue;
10709
10710 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10711 * active, fixed, or single-aggregated with another binary variable
10712 */
10713 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10714 continue;
10715
10716 if ( SCIPdoNotMultaggrVar(scip, var) )
10717 continue;
10718
10719 val = consdata->vals[i];
10720 obj = SCIPvarGetObj(var);
10721 lb = SCIPvarGetLbGlobal(var);
10722 ub = SCIPvarGetUbGlobal(var);
10723
10724 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10725 *
10726 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10727 * - constraint is the only one that forbids fixing the variable to its lower bound
10728 * - 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
10729 *
10730 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10731 * - constraint is the only one that forbids fixing the variable to its upper bound
10732 * - 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
10733 *
10734 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10735 * - constraint is the only one that forbids fixing the variable to its upper bound
10736 * - 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
10737 *
10738 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10739 * - constraint is the only one that forbids fixing the variable to its lower bound
10740 * - 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
10741 *
10742 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10743 * of all x_j
10744 * furthermore: we only want to apply this, if no fill-in will be produced
10745 */
10746 agglhs = lhsexists
10747 && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10748 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10749 || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10750 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10751 aggrhs = rhsexists
10752 && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10753 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10754 || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10755 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10756 if( agglhs || aggrhs )
10757 {
10758 SCIP_Real minresactivity;
10759 SCIP_Real maxresactivity;
10760 SCIP_Real minval;
10761 SCIP_Real maxval;
10762 SCIP_Bool ismintight;
10763 SCIP_Bool ismaxtight;
10764 SCIP_Bool isminsettoinfinity;
10765 SCIP_Bool ismaxsettoinfinity;
10766
10767 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10768 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10769 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
10770 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10771
10772 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10773 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10774 * This is needed, because we do not want to rely on relaxed finite resactivities.
10775 */
10776 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
10777
10778 if( agglhs )
10779 {
10780 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10781 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10782
10783 assert(SCIPisLE(scip, minval, maxval));
10784 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10785 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10786 {
10787 SCIP_Real oldmaxresactivity;
10788 SCIP_Real oldminresactivity;
10789 SCIP_Bool recalculated;
10790
10791 recalculated = FALSE;
10792 oldmaxresactivity = maxresactivity;
10793 oldminresactivity = minresactivity;
10794
10795 /* check minresactivity for reliability */
10796 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10797 {
10798 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10799 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10800 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10801 }
10802
10803 /* check maxresactivity for reliability */
10804 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10805 {
10806 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10807 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10808 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10809 }
10810
10811 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10812 if( recalculated )
10813 {
10814 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10815
10816 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10817 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10818
10819 assert(SCIPisLE(scip, minval, maxval));
10820 }
10821
10822 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10823 {
10824 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10825 * in the multi-aggregation
10826 */
10827 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10828 {
10829 bestpos = i;
10830 bestisint = isint;
10831 bestislhs = TRUE;
10832 continue; /* no need to also look at the right hand side */
10833 }
10834 }
10835 }
10836 }
10837
10838 if( aggrhs )
10839 {
10840 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10841 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10842
10843 assert(SCIPisLE(scip,minval,maxval));
10844 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10845 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10846 {
10847 SCIP_Real oldmaxresactivity;
10848 SCIP_Real oldminresactivity;
10849 SCIP_Bool recalculated;
10850
10851 recalculated = FALSE;
10852 oldmaxresactivity = maxresactivity;
10853 oldminresactivity = minresactivity;
10854
10855 /* check minresactivity for reliability */
10856 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10857 {
10858 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10859 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10860 }
10861
10862 /* check maxresactivity for reliability */
10863 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10864 {
10865 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10866 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10867 }
10868
10869 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10870 if( recalculated )
10871 {
10872 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10873 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10874 assert(SCIPisLE(scip,minval,maxval));
10875 }
10876
10877 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10878 {
10879 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10880 * in the multi-aggregation
10881 */
10882 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10883 {
10884 bestpos = i;
10885 bestisint = isint;
10886 bestislhs = FALSE;
10887 }
10888 }
10889 }
10890 }
10891 }
10892 }
10893
10894 if( bestpos >= 0 )
10895 {
10896 SCIP_VAR** aggrvars;
10897 SCIP_Real* aggrcoefs;
10898 SCIP_Real aggrconst;
10899 SCIP_VAR* bestvar;
10900 SCIP_Real bestval;
10901 SCIP_Real epsilon;
10902 int naggrs;
10903 int j;
10904 SCIP_Bool infeasible;
10905 SCIP_Bool aggregated;
10906 SCIP_Bool samevar;
10907 int supinf; /* counter for infinite contributions to the supremum of a possible
10908 * multi-aggregation
10909 */
10910 int infinf; /* counter for infinite contributions to the infimum of a possible
10911 * multi-aggregation
10912 */
10913
10914 assert(!bestislhs || lhsexists);
10915 assert(bestislhs || rhsexists);
10916
10917 bestvar = consdata->vars[bestpos];
10918 bestval = consdata->vals[bestpos];
10919 assert(bestisint ==
10921
10922 /* allocate temporary memory */
10923 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10924 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10925
10926 /* set up the multi-aggregation */
10928 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10929 naggrs = 0;
10930 supinf = 0;
10931 infinf = 0;
10932 samevar = FALSE;
10933 epsilon = SCIPepsilon(scip);
10934
10935 for( j = 0; j < consdata->nvars; ++j )
10936 {
10937 if( j != bestpos )
10938 {
10939 SCIP_Real absaggrcoef;
10940
10941 aggrvars[naggrs] = consdata->vars[j];
10942 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10943 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10944
10945 absaggrcoef = REALABS(aggrcoefs[naggrs]);
10946
10947 /* do not try to multi aggregate, when numerical bad */
10948 if( absaggrcoef < epsilon )
10949 {
10950 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10951
10952 /* free temporary memory */
10953 SCIPfreeBufferArray(scip, &aggrcoefs);
10954 SCIPfreeBufferArray(scip, &aggrvars);
10955
10956 return SCIP_OKAY;
10957 }
10958
10959 if( bestisint )
10960 {
10961 /* coefficient must be integral: round it to exact integral value */
10962 assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10963 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10964 }
10965
10966 if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10967 {
10968 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10969 {
10970 ++supinf;
10971 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10972 {
10973 ++infinf;
10974 samevar = TRUE;
10975 }
10976 }
10977 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10978 ++infinf;
10979 }
10980 else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
10981 {
10982 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10983 {
10984 ++supinf;
10985 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10986 {
10987 ++infinf;
10988 samevar = TRUE;
10989 }
10990 }
10991 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10992 ++infinf;
10993 }
10994
10995 naggrs++;
10996 }
10997 }
10998 assert(!samevar || (supinf > 0 && infinf > 0));
10999
11000 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11001 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11002 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
11003 assert(naggrs == consdata->nvars-1);
11004
11005 /* right hand side must be integral: round it to exact integral value */
11006 if( bestisint )
11007 {
11008 assert(SCIPisIntegral(scip, aggrconst));
11009 aggrconst = SCIPfloor(scip, aggrconst+0.5);
11010 }
11011
11012 aggregated = FALSE;
11013 infeasible = FALSE;
11014
11015 /* perform the multi-aggregation */
11016 if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11017 {
11018 /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11019 * also convertLongEquality() early termination due to coefficients
11020 */
11021 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11022
11023 /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11024 * the implicitness might rely on the constraint and the integrality of bestvar
11025 */
11026 if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11027 {
11028 SCIP_Bool infeasiblevartypechg;
11029
11030 for( j = 0; j < naggrs; ++j)
11031 {
11032 /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11033 * lead to infeasibility
11034 */
11035 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT )
11036 {
11037 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
11038 (*nchgvartypes)++;
11039 assert(!infeasiblevartypechg);
11040 }
11041 }
11042 }
11043 }
11044 else
11045 {
11046 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11047 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11048 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11049 }
11050 /* free temporary memory */
11051 SCIPfreeBufferArray(scip, &aggrcoefs);
11052 SCIPfreeBufferArray(scip, &aggrvars);
11053
11054 /* check for infeasible aggregation */
11055 if( infeasible )
11056 {
11057 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11058 *cutoff = TRUE;
11059 return SCIP_OKAY;
11060 }
11061
11062 /* delete the constraint, if the aggregation was successful */
11063 if( aggregated )
11064 {
11065 SCIP_CALL( SCIPdelCons(scip, cons) );
11066
11067 if( !consdata->upgraded )
11068 (*ndelconss)++;
11069 (*naggrvars)++;
11070 }
11071 else
11072 {
11073 SCIPdebugMsg(scip, "aggregation non successful!\n");
11074 }
11075 }
11076
11077 return SCIP_OKAY;
11078}
11079
11080#define BINWEIGHT 1
11081#define INTWEIGHT 4
11082#define CONTWEIGHT 8
11083
11084/** gets weight for variable in a "weighted number of variables" sum */
11085static
11087 SCIP_VAR* var /**< variable to get weight for */
11088 )
11089{
11090 switch( SCIPvarGetType(var) )
11091 {
11093 return BINWEIGHT;
11096 return INTWEIGHT;
11098 return CONTWEIGHT;
11099 default:
11100 SCIPerrorMessage("invalid variable type\n");
11101 SCIPABORT();
11102 return 0; /*lint !e527*/
11103 }
11104}
11105
11106/** tries to aggregate variables in equations a^Tx = lhs
11107 * in case there are at most two binary variables with an odd coefficient and all other
11108 * variables are not continuous and have an even coefficient then:
11109 * - exactly one odd binary variables
11110 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11111 * - lhs is odd -> y = 1
11112 * - lhs is even -> y = 0
11113 * - exactly two odd binary variables
11114 * aggregate the two binary variables with odd coefficient
11115 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11116 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11117 */
11118static
11120 SCIP* scip, /**< SCIP data structure */
11121 SCIP_CONS* cons, /**< linear constraint */
11122 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11123 int* nfixedvars, /**< pointer to count number of fixed variables */
11124 int* naggrvars /**< pointer to count number of aggregated variables */
11125 )
11126{ /*lint --e{715}*/
11127 SCIP_CONSDATA* consdata;
11128 SCIP_Bool success;
11129
11130 assert( scip != NULL );
11131 assert( cons != NULL );
11132
11133 consdata = SCIPconsGetData(cons);
11134 assert( consdata != NULL );
11135
11136 /* check if the linear constraint is an equation with integral right hand side */
11137 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11138 return SCIP_OKAY;
11139
11140 /* try to fix and aggregated variables until nothing is possible anymore */
11141 do
11142 {
11143 int v;
11144 int nvars;
11145 SCIP_VAR** vars;
11146 SCIP_Real* vals;
11147 SCIP_Real lhs;
11148 SCIP_Bool lhsodd;
11149
11150 SCIP_Bool infeasible;
11151 SCIP_Bool fixed;
11152 SCIP_Bool aggregated;
11153 SCIP_Bool redundant;
11154
11155 SCIP_VAR* var1;
11156 SCIP_VAR* var2;
11157 int noddvars;
11158
11159 success = FALSE;
11160
11161 lhs = consdata->lhs;
11162 vars = consdata->vars;
11163 vals = consdata->vals;
11164 nvars = consdata->nvars;
11165
11166 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11167
11168 var1 = NULL;
11169 var2 = NULL;
11170 noddvars = 0;
11171
11172 /* search for binary variables with an odd coefficient */
11173 for( v = 0; v < nvars && noddvars < 3; ++v )
11174 {
11175 SCIP_Longint val;
11176
11177 /* all coefficients and variables have to be integral */
11178 if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11179 return SCIP_OKAY;
11180
11181 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11182 if( val % 2 != 0 )
11183 {
11184 /* the odd values have to belong to binary variables */
11185 if( !SCIPvarIsBinary(vars[v]) )
11186 return SCIP_OKAY;
11187
11188 if( noddvars == 0 )
11189 var1 = vars[v];
11190 else
11191 var2 = vars[v];
11192
11193 noddvars++;
11194 }
11195 }
11196
11197 /* check lhs is odd or even */
11198 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11199
11200 if( noddvars == 1 )
11201 {
11202 assert( var1 != NULL );
11203
11204 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11205 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11206
11207 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11208
11209 /* check for infeasibility of fixing */
11210 if( infeasible )
11211 {
11212 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11213 *cutoff = TRUE;
11214 return SCIP_OKAY;
11215 }
11216
11217 if( fixed )
11218 {
11219 SCIPdebugMsg(scip, " -> feasible fixing\n");
11220 (*nfixedvars)++;
11221 success = TRUE;
11222 }
11223 }
11224 else if( noddvars == 2 )
11225 {
11226 assert( var1 != NULL );
11227 assert( var2 != NULL );
11228
11229 /* aggregate the two variables with odd coefficient
11230 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11231 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11232 */
11233 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11234 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11235
11236 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11237 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11238
11239 /* check for infeasibility of aggregation */
11240 if( infeasible )
11241 {
11242 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11243 *cutoff = TRUE;
11244 return SCIP_OKAY;
11245 }
11246
11247 /* count the aggregation */
11248 if( aggregated )
11249 {
11250 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11251 (*naggrvars)++;
11252 success = TRUE;
11253 }
11254 }
11255
11256 if( success )
11257 {
11258 /* apply fixings and aggregation to successfully rerun this presolving step */
11259 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11260
11261 if( infeasible )
11262 {
11263 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11264 *cutoff = TRUE;
11265 return SCIP_OKAY;
11266 }
11267
11268 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11269
11270 if( infeasible )
11271 {
11272 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11273 *cutoff = TRUE;
11274 return SCIP_OKAY;
11275 }
11276 }
11277 }
11278 while( success && consdata->nvars >= 1 );
11279
11280 return SCIP_OKAY;
11281}
11282
11283
11284
11285/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11286 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11287 * coefficients
11288 */
11289static
11291{ /*lint --e{715}*/
11292 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11293 SCIP_VARTYPE vartype1;
11294 SCIP_VARTYPE vartype2;
11295 SCIP_Real value;
11296
11297 assert(consdata != NULL);
11298 assert(0 <= ind1 && ind1 < consdata->nvars);
11299 assert(0 <= ind2 && ind2 < consdata->nvars);
11300
11301 vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11302 vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11303
11304 if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11305 {
11306 /* continuous varibles will be sorted to the back */
11307 if( vartype2 != vartype1 )
11308 return +1;
11309 /* both variables are continuous */
11310 else
11311 return 0;
11312 }
11313 /* continuous variables will be sorted to the back */
11314 else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11315 return -1;
11316
11317 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11318
11319 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11320 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11321}
11322
11323/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11324 *
11325 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11326 * then we can change this constraint to 1^Tx = 1
11327 */
11328static
11330 SCIP* scip, /**< SCIP data structure */
11331 SCIP_CONS* cons, /**< linear constraint */
11332 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11333 int* nchgsides /**< pointer to store the amount of changed sides */
11334 )
11335{
11336 SCIP_CONSDATA* consdata;
11337 SCIP_VAR** vars;
11338 SCIP_Real* vals;
11339 SCIP_Real minval;
11340 SCIP_Real secondminval;
11341 SCIP_Real maxval;
11342 SCIP_Real lhs;
11343 SCIP_Real rhs;
11344 int nvars;
11345 int v;
11346
11347 /* we must not change a modifiable constraint in any way */
11348 if( SCIPconsIsModifiable(cons) )
11349 return SCIP_OKAY;
11350
11351 if( SCIPconsIsDeleted(cons) )
11352 return SCIP_OKAY;
11353
11354 consdata = SCIPconsGetData(cons);
11355 assert(consdata != NULL);
11356
11357 nvars = consdata->nvars;
11358
11359 /* do not check empty or bound-constraints */
11360 if( nvars < 2 )
11361 return SCIP_OKAY;
11362
11363 lhs = consdata->lhs;
11364 rhs = consdata->rhs;
11365 assert(!SCIPisInfinity(scip, -lhs));
11366 assert(!SCIPisInfinity(scip, rhs));
11367 assert(!SCIPisNegative(scip, rhs));
11368
11369 /* sides must be positive and different to detect set partition */
11370 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11371 return SCIP_OKAY;
11372
11373 vals = consdata->vals;
11374 vars = consdata->vars;
11375 assert(vars != NULL);
11376 assert(vals != NULL);
11377
11378 minval = SCIP_INVALID;
11379 secondminval = SCIP_INVALID;
11380 maxval = -SCIP_INVALID;
11381
11382 for( v = nvars - 1; v >= 0; --v )
11383 {
11384 if( SCIPvarIsBinary(vars[v]) )
11385 {
11386 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11387 {
11388 secondminval = minval;
11389 minval = vals[v];
11390 }
11391 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11392 secondminval = vals[v];
11393
11394 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11395 maxval = vals[v];
11396 }
11397 else
11398 break;
11399 }
11400
11401 /* check if all variables are binary, we can choose one, and need to choose at most one */
11402 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11403 && SCIPisGT(scip, minval + secondminval, rhs) )
11404 {
11405 /* change all coefficients to 1.0 */
11406 for( v = nvars - 1; v >= 0; --v )
11407 {
11408 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11409 }
11410 (*nchgcoefs) += nvars;
11411
11412 /* replace old right and left hand side with 1.0 */
11413 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11414 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11415 (*nchgsides) += 2;
11416 }
11417
11418 return SCIP_OKAY;
11419}
11420
11421/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11422 *
11423 * for both-sided constraints only @see rangedRowSimplify() will be called
11424 *
11425 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11426 *
11427 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11428 *
11429 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11430 *
11431 * 2. We try to remove redundant fractional parts in a constraint
11432 *
11433 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11434 *
11435 * 3. We are using the greatest common divisor for further reductions
11436 *
11437 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11438 * integral
11439 */
11440static
11442 SCIP* scip, /**< SCIP data structure */
11443 SCIP_CONS* cons, /**< linear constraint */
11444 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11445 int* nchgsides, /**< pointer to store the amount of changed sides */
11446 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11447 )
11448{
11449 SCIP_CONSDATA* consdata;
11450 SCIP_VAR** vars;
11451 SCIP_Real* vals;
11452 int* perm;
11453 SCIP_Real minactsub;
11454 SCIP_Real maxactsub;
11455 SCIP_Real siderest;
11456 SCIP_Real feastol;
11457 SCIP_Real newcoef;
11458 SCIP_Real absval;
11459 SCIP_Real minact;
11460 SCIP_Real maxact;
11461 SCIP_Real side;
11462 SCIP_Real lhs;
11463 SCIP_Real rhs;
11464 SCIP_Real lb;
11465 SCIP_Real ub;
11466 SCIP_Longint restcoef;
11467 SCIP_Longint oldgcd;
11468 SCIP_Longint rest;
11469 SCIP_Longint gcd;
11470 SCIP_Bool isminsettoinfinity;
11471 SCIP_Bool ismaxsettoinfinity;
11472 SCIP_Bool ismintight;
11473 SCIP_Bool ismaxtight;
11474 SCIP_Bool allcoefintegral;
11475 SCIP_Bool onlybin;
11476 SCIP_Bool hasrhs;
11477 SCIP_Bool haslhs;
11478 int oldnchgcoefs;
11479 int oldnchgsides;
11480 int foundbin;
11481 int candpos;
11482 int candpos2;
11483 int offsetv;
11484 int nvars;
11485 int v;
11486 int w;
11487
11488 assert(scip != NULL);
11489 assert(cons != NULL);
11490 assert(nchgcoefs != NULL);
11491 assert(nchgsides != NULL);
11492
11493 *infeasible = FALSE;
11494
11495 /* we must not change a modifiable constraint in any way */
11496 if( SCIPconsIsModifiable(cons) )
11497 return SCIP_OKAY;
11498
11499 if( SCIPconsIsDeleted(cons) )
11500 return SCIP_OKAY;
11501
11502 consdata = SCIPconsGetData(cons);
11503 assert(consdata != NULL);
11504
11505 nvars = consdata->nvars;
11506
11507 /* do not check empty or bound-constraints */
11508 if( nvars <= 2 )
11509 return SCIP_OKAY;
11510
11511 /* update maximal activity delta if necessary */
11512 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11514
11515 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11516 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11517 checkMaxActivityDelta(scip, consdata);
11518
11519 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11520 * accordingly
11521 */
11522 /* can only work with valid non-infinity activities per variable */
11523 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11524 return SCIP_OKAY;
11525
11526 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11527 * but the eventsystem seems to be full
11528 */
11529 consdata->normalized = FALSE;
11530
11531 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11532 assert(nvars == consdata->nvars);
11533
11534 if( *infeasible )
11535 return SCIP_OKAY;
11536
11537 if( !consdata->normalized )
11538 return SCIP_OKAY;
11539
11540 lhs = consdata->lhs;
11541 rhs = consdata->rhs;
11542 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11543 assert(!SCIPisNegative(scip, rhs));
11544
11545 if( !SCIPisInfinity(scip, -lhs) )
11546 haslhs = TRUE;
11547 else
11548 haslhs = FALSE;
11549
11550 if( !SCIPisInfinity(scip, rhs) )
11551 hasrhs = TRUE;
11552 else
11553 hasrhs = FALSE;
11554
11555 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11556 SCIPdebug( oldnchgsides = *nchgsides; )
11557
11558 /* @todo extend both-sided simplification */
11559 if( haslhs && hasrhs )
11560 {
11561 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11562
11563 return SCIP_OKAY;
11564 }
11565 assert(haslhs != hasrhs);
11566
11567 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11568 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11569 assert(!haslhs || !SCIPisNegative(scip, lhs));
11570
11571 /* get temporary memory to store the sorted permutation */
11572 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11573
11574 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11575 * value of their coefficients
11576 */
11577 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11578
11579 /* perform sorting after permutation array */
11580 permSortConsdata(consdata, perm, nvars);
11581 consdata->indexsorted = FALSE;
11582 consdata->coefsorted = FALSE;
11583
11584 vars = consdata->vars;
11585 vals = consdata->vals;
11586 assert(vars != NULL);
11587 assert(vals != NULL);
11588 assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11589
11590 /* free temporary memory */
11591 SCIPfreeBufferArray(scip, &perm);
11592
11593 /* only check constraints with at least two non continuous variables */
11594 if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11595 return SCIP_OKAY;
11596
11597 /* do not process constraints when all coefficients are 1.0 */
11598 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11599 return SCIP_OKAY;
11600
11601 feastol = SCIPfeastol(scip);
11602
11603 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11605
11606 /* get global activities */
11607 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11608 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
11609
11610 /* cannot work with infinite activities */
11611 if( isminsettoinfinity || ismaxsettoinfinity )
11612 return SCIP_OKAY;
11613
11614 assert(ismintight);
11615 assert(ismaxtight);
11616 assert(maxact > minact);
11617 assert(!SCIPisInfinity(scip, -minact));
11618 assert(!SCIPisInfinity(scip, maxact));
11619
11620 v = 0;
11621 offsetv = -1;
11622 side = haslhs ? lhs : rhs;
11623 minactsub = minact;
11624 maxactsub = maxact;
11625
11626 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11627 * do not need to look at the large coefficients
11628 *
11629 * e.g. all x are binary, z are positive integer
11630 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11631 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11632 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11633 *
11634 * can be changed to
11635 *
11636 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11637 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11638 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11639 */
11640
11641 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11642 * hand side, we cannot apply the extra reduction step and need to reset v
11643 *
11644 * 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
11645 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11646 * for all i is a solution
11647 *
11648 * also redundancy of variables would not be correctly determined in such a case
11649 */
11650 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11651 {
11652 v = 1;
11653
11654 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11655 {
11656 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11657 * extra step, which might have worked
11658 */
11659 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11660 {
11661 v = 0;
11662 break;
11663 }
11664
11665 ++v;
11666 }
11667
11668 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11669 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11670 if( v == nvars )
11671 return SCIP_OKAY;
11672
11673 /* cannot work with continuous variables which have a big coefficient */
11674 if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11675 return SCIP_OKAY;
11676
11677 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11678 if( SCIPisEQ(scip, side, -vals[v]) )
11679 v = 0;
11680
11681 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11682 * reduction
11683 */
11684 if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11685 v = 0;
11686
11687 if( v > 0 )
11688 {
11689 assert(v < nvars);
11690
11691 offsetv = v - 1;
11692
11693 for( w = 0; w < v; ++w )
11694 {
11695 lb = SCIPvarGetLbGlobal(vars[w]);
11696 ub = SCIPvarGetUbGlobal(vars[w]);
11697
11698 assert(vals[w] > 0);
11699
11700 /* update residual activities */
11701 maxactsub -= ub * vals[w];
11702 minactsub -= lb * vals[w];
11703 assert(maxactsub > minactsub);
11704 }
11705 }
11706 }
11707
11708 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11709 *
11710 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11711 *
11712 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11713 * to
11714 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11715 */
11716 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11717 {
11718 SCIP_Bool redundant = FALSE;
11719 SCIP_Bool numericsok;
11720 SCIP_Bool rredundant;
11721 SCIP_Bool lredundant;
11722
11723 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11724 assert(gcd >= 1);
11725
11726 if( v == 0 )
11727 {
11728 lb = SCIPvarGetLbGlobal(vars[0]);
11729 ub = SCIPvarGetUbGlobal(vars[0]);
11730
11731 /* update residual activities */
11732 if( vals[0] > 0 )
11733 {
11734 maxactsub -= ub * vals[0];
11735 minactsub -= lb * vals[0];
11736 }
11737 else
11738 {
11739 maxactsub -= lb * vals[0];
11740 minactsub -= ub * vals[0];
11741 }
11742 assert(maxactsub > minactsub);
11743 ++v;
11744 }
11745
11746 siderest = -SCIP_INVALID;
11747 allcoefintegral = TRUE;
11748
11749 /* check if some variables always fit into the given constraint */
11750 for( ; v < nvars - 1; ++v )
11751 {
11752 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11753 break;
11754
11755 if( !SCIPisIntegral(scip, vals[v]) )
11756 {
11757 allcoefintegral = FALSE;
11758 break;
11759 }
11760
11761 /* calculate greatest common divisor for all general and binary variables */
11762 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11763
11764 if( gcd == 1 )
11765 break;
11766
11767 lb = SCIPvarGetLbGlobal(vars[v]);
11768 ub = SCIPvarGetUbGlobal(vars[v]);
11769
11770 assert(!SCIPisInfinity(scip, -lb));
11771 assert(!SCIPisInfinity(scip, ub));
11772
11773 /* update residual activities */
11774 if( vals[v] > 0 )
11775 {
11776 maxactsub -= ub * vals[v];
11777 minactsub -= lb * vals[v];
11778 }
11779 else
11780 {
11781 maxactsub -= lb * vals[v];
11782 minactsub -= ub * vals[v];
11783 }
11784 assert(SCIPisGE(scip, maxactsub, minactsub));
11785
11786 if( hasrhs )
11787 {
11788 /* determine the remainder of the right hand side and the gcd */
11789 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11790 }
11791 else
11792 {
11793 /* determine the remainder of the left hand side and the gcd */
11794 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11795 if( SCIPisZero(scip, siderest) )
11796 siderest = gcd;
11797 }
11798
11799 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11800 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11801
11802 /* early termination if the activities deceed the gcd */
11803 if( offsetv == -1 && (rredundant || lredundant) )
11804 {
11805 redundant = TRUE;
11806 break;
11807 }
11808 }
11809 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11810
11811 if( !redundant )
11812 {
11813 if( hasrhs )
11814 {
11815 /* determine the remainder of the right hand side and the gcd */
11816 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11817 }
11818 else
11819 {
11820 /* determine the remainder of the left hand side and the gcd */
11821 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11822 if( SCIPisZero(scip, siderest) )
11823 siderest = gcd;
11824 }
11825 }
11826 else
11827 ++v;
11828
11829 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",
11830 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11831
11832 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11833 * reasonable absolute values */
11834 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11835 REALABS(minactsub) < MAXACTVAL;
11836
11837 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11838 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11839
11840 /* check if we can remove redundant variables */
11841 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11842 {
11843 SCIP_Real oldcoef;
11844
11845 /* double check the redundancy */
11846#ifndef NDEBUG
11847 SCIP_Real tmpminactsub = 0.0;
11848 SCIP_Real tmpmaxactsub = 0.0;
11849
11850 /* recompute residual activities */
11851 for( w = v; w < nvars; ++w )
11852 {
11853 lb = SCIPvarGetLbGlobal(vars[w]);
11854 ub = SCIPvarGetUbGlobal(vars[w]);
11855
11856 assert(!SCIPisInfinity(scip, -lb));
11857 assert(!SCIPisInfinity(scip, ub));
11858
11859 /* update residual activities */
11860 if( vals[w] > 0 )
11861 {
11862 tmpmaxactsub += ub * vals[w];
11863 tmpminactsub += lb * vals[w];
11864 }
11865 else
11866 {
11867 tmpmaxactsub += lb * vals[w];
11868 tmpminactsub += ub * vals[w];
11869 }
11870 assert(tmpmaxactsub >= tmpminactsub);
11871 }
11872
11873 if( hasrhs )
11874 {
11875 assert(offsetv == -1);
11876
11877 /* determine the remainder of the right hand side and the gcd */
11878 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11879 }
11880 else
11881 {
11882 /* determine the remainder of the left hand side and the gcd */
11883 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11884 if( SCIPisZero(scip, siderest) )
11885 siderest = gcd;
11886 }
11887
11888 /* is the redundancy really fulfilled */
11889 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11890 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11891#endif
11892
11893 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11894 nvars - v, SCIPconsGetName(cons));
11895
11896 /* remove redundant variables */
11897 for( w = nvars - 1; w >= v; --w )
11898 {
11899 SCIP_CALL( delCoefPos(scip, cons, w) );
11900 }
11901 (*nchgcoefs) += (nvars - v);
11902
11903 assert(w >= 0);
11904
11905 oldcoef = vals[w];
11906
11907 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11908 assert(vars == consdata->vars);
11909 assert(vals == consdata->vals);
11910 assert(w < consdata->nvars);
11911
11912 if( *infeasible )
11913 return SCIP_OKAY;
11914
11915 /* compute new greatest common divisor due to normalization */
11916 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11917 assert(gcd >= 1);
11918
11919 /* update side */
11920 if( hasrhs )
11921 {
11922 /* replace old with new right hand side */
11923 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11924 rhs = consdata->rhs;
11925 }
11926 else
11927 {
11928 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11929 {
11930 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11931 lhs = consdata->lhs;
11932 }
11933 else
11934 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11935 }
11936 ++(*nchgsides);
11937
11938 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11939 assert(!haslhs || !SCIPisNegative(scip, lhs));
11940
11941 /* get new constraint data */
11942 nvars = consdata->nvars;
11943 assert(nvars > 0);
11944
11945 allcoefintegral = TRUE;
11946
11947#ifndef NDEBUG
11948 /* check integrality */
11949 for( w = offsetv + 1; w < nvars; ++w )
11950 {
11951 assert(SCIPisIntegral(scip, vals[w]));
11952 }
11953#endif
11955 }
11956
11957 /* try to find a better gcd, when having large coefficients */
11958 if( offsetv >= 0 && gcd == 1 )
11959 {
11960 /* calculate greatest common divisor for all general variables */
11961 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11962
11963 if( gcd > 1 )
11964 {
11965 gcd = -1;
11966 candpos = -1;
11967
11968 for( v = nvars - 1; v > offsetv; --v )
11969 {
11970 assert(!SCIPisZero(scip, vals[v]));
11971 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11972 break;
11973
11974 if( !SCIPisIntegral(scip, vals[v]) )
11975 {
11976 allcoefintegral = FALSE;
11977 break;
11978 }
11979
11980 oldgcd = gcd;
11981
11982 if( gcd == -1 )
11983 {
11984 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11985 assert(gcd >= 1);
11986 }
11987 else
11988 {
11989 /* calculate greatest common divisor for all general and binary variables */
11990 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11991 }
11992
11993 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11994 * can stop searching
11995 */
11996 if( gcd == 1 )
11997 {
11998 if( !SCIPvarIsBinary(vars[v]) )
11999 break;
12000
12001 /* found candidate */
12002 if( candpos == -1 )
12003 {
12004 gcd = oldgcd;
12005 candpos = v;
12006 }
12007 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12008 else
12009 break;
12010 }
12011 }
12012 assert(v > offsetv || candpos > offsetv);
12013 }
12014 else
12015 candpos = -1;
12016 }
12017 else
12018 candpos = nvars - 1;
12019
12020 /* check last coefficient for integrality */
12021 if( gcd > 1 && allcoefintegral && !redundant )
12022 {
12023 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12024 allcoefintegral = FALSE;
12025 }
12026
12027 /* check for further necessary coefficient adjustments */
12028 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12029 {
12030 assert(offsetv + 1 < nvars);
12031 assert(0 <= candpos && candpos < nvars);
12032
12033 if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12034 {
12035 SCIP_Bool notchangable = FALSE;
12036
12037#ifndef NDEBUG
12038 /* check integrality */
12039 for( w = offsetv + 1; w < nvars; ++w )
12040 {
12041 assert(SCIPisIntegral(scip, vals[w]));
12042 }
12043#endif
12044
12045 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12046 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12047 {
12048 /* determine the remainder of the side and the gcd */
12049 if( hasrhs )
12050 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12051 else
12052 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12053 assert(rest >= 0);
12054 assert(rest < gcd);
12055
12056 /* determine the remainder of the coefficient candidate and the gcd */
12057 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12058 assert(restcoef >= 1);
12059 assert(restcoef < gcd);
12060
12061 if( hasrhs )
12062 {
12063 /* calculate new coefficient */
12064 if( restcoef > rest )
12065 newcoef = vals[candpos] - restcoef + gcd;
12066 else
12067 newcoef = vals[candpos] - restcoef;
12068 }
12069 else
12070 {
12071 /* calculate new coefficient */
12072 if( rest == 0 || restcoef < rest )
12073 newcoef = vals[candpos] - restcoef;
12074 else
12075 newcoef = vals[candpos] - restcoef + gcd;
12076 }
12077
12078 /* done */
12079
12080 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12081 * another with the big coefficient was set to 1
12082 */
12083 if( hasrhs && SCIPisZero(scip, newcoef) )
12084 {
12085 notchangable = TRUE;
12086 }
12087 else if( SCIPisZero(scip, newcoef) )
12088 {
12089 /* delete old redundant coefficient */
12090 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12091 ++(*nchgcoefs);
12092 }
12093 else
12094 {
12095 /* replace old with new coefficient */
12096 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12097 ++(*nchgcoefs);
12098 }
12099 }
12100 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12101 {
12102 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12103 }
12104
12105 /* correct side and big coefficients */
12106 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12107 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12108 {
12109 if( haslhs )
12110 {
12111 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12112
12113 SCIP_CALL( chgLhs(scip, cons, newcoef) );
12114 ++(*nchgsides);
12115 }
12116 else
12117 {
12118 assert(hasrhs);
12119 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12120
12121 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12122 ++(*nchgsides);
12123 }
12124
12125 /* correct coefficients up front */
12126 for( w = offsetv; w >= 0; --w )
12127 {
12128 assert(vals[w] > 0);
12129
12130 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12131 }
12132 (*nchgcoefs) += (offsetv + 1);
12133 }
12134
12135 if( !notchangable )
12136 {
12137 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12138 assert(vars == consdata->vars);
12139 assert(vals == consdata->vals);
12140
12141 if( *infeasible )
12142 return SCIP_OKAY;
12143
12144 /* get new constraint data */
12145 nvars = consdata->nvars;
12146 assert(nvars >= 2);
12147
12149
12150 lhs = consdata->lhs;
12151 rhs = consdata->rhs;
12152 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12153 assert(!haslhs || !SCIPisNegative(scip, lhs));
12154 }
12155 }
12156 }
12157 }
12158
12159 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12160 /* no continuous variables are left over */
12161 if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12162 return SCIP_OKAY;
12163
12164 onlybin = TRUE;
12165 allcoefintegral = TRUE;
12166 /* check if all variables are of binary type */
12167 for( v = nvars - 1; v >= 0; --v )
12168 {
12169 if( !SCIPvarIsBinary(vars[v]) )
12170 onlybin = FALSE;
12171 if( !SCIPisIntegral(scip, vals[v]) )
12172 allcoefintegral = FALSE;
12173 }
12174
12175 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12176 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12177 *
12178 * @todo there are some steps missing ....
12179 */
12180 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12181 {
12182 SCIP_Real val;
12183 SCIP_Real newval;
12184 SCIP_Real frac = 0.0;
12185 SCIP_Bool found = FALSE;
12186
12187 if( hasrhs )
12188 {
12189 if( allcoefintegral )
12190 {
12191 /* replace old with new right hand side */
12192 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12193 ++(*nchgsides);
12194 }
12195 else
12196 {
12197 siderest = rhs - SCIPfloor(scip, rhs);
12198
12199 /* try to round down all non-integral coefficients */
12200 for( v = nvars - 1; v >= 0; --v )
12201 {
12202 val = vals[v];
12203
12204 /* add up all possible fractional parts */
12205 if( !SCIPisIntegral(scip, val) )
12206 {
12207 lb = SCIPvarGetLbGlobal(vars[v]);
12208 ub = SCIPvarGetUbGlobal(vars[v]);
12209
12210 /* at least one bound need to be at zero */
12211 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12212 return SCIP_OKAY;
12213
12214 /* swap bounds for 'standard' form */
12215 if( !SCIPisFeasZero(scip, lb) )
12216 {
12217 ub = lb;
12218 val *= -1;
12219 }
12220
12221 found = TRUE;
12222
12223 frac += (val - SCIPfloor(scip, val)) * ub;
12224
12225 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12226 *
12227 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12228 * x3, x4 set to 1 would be infeasible but feasible after flooring
12229 */
12230 if( SCIPisGT(scip, frac, siderest) )
12231 return SCIP_OKAY;
12232 }
12233 }
12234 assert(v == -1);
12235
12236 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12237
12238 /* round rhs and coefficients to integral values */
12239 if( found )
12240 {
12241 for( v = nvars - 1; v >= 0; --v )
12242 {
12243 val = vals[v];
12244
12245 /* add the whole fractional part */
12246 if( !SCIPisIntegral(scip, val) )
12247 {
12248 lb = SCIPvarGetLbGlobal(vars[v]);
12249
12250 if( SCIPisFeasZero(scip, lb) )
12251 newval = SCIPfloor(scip, val);
12252 else
12253 newval = SCIPceil(scip, val);
12254
12255 if( SCIPisZero(scip, newval) )
12256 {
12257 /* delete old redundant coefficient */
12258 SCIP_CALL( delCoefPos(scip, cons, v) );
12259 ++(*nchgcoefs);
12260 }
12261 else
12262 {
12263 /* replace old with new coefficient */
12264 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12265 ++(*nchgcoefs);
12266 }
12267 }
12268 }
12269 }
12270
12271 /* replace old with new right hand side */
12272 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12273 ++(*nchgsides);
12274 }
12275 }
12276 else
12277 {
12278 if( allcoefintegral )
12279 {
12280 /* replace old with new left hand side */
12281 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12282 ++(*nchgsides);
12283 }
12284 else
12285 {
12286 /* cannot floor left hand side to zero */
12287 if( SCIPisLT(scip, lhs, 1.0) )
12288 return SCIP_OKAY;
12289
12290 siderest = lhs - SCIPfloor(scip, lhs);
12291
12292 /* try to round down all non-integral coefficients */
12293 for( v = nvars - 1; v >= 0; --v )
12294 {
12295 val = vals[v];
12296
12297 /* add up all possible fractional parts */
12298 if( !SCIPisIntegral(scip, val) )
12299 {
12300 lb = SCIPvarGetLbGlobal(vars[v]);
12301 ub = SCIPvarGetUbGlobal(vars[v]);
12302
12303 /* at least one bound need to be at zero */
12304 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12305 return SCIP_OKAY;
12306
12307 /* swap bounds for 'standard' form */
12308 if( !SCIPisFeasZero(scip, lb) )
12309 {
12310 ub = lb;
12311 val *= -1;
12312 }
12313
12314 /* cannot floor to zero */
12315 if( SCIPisLT(scip, val, 1.0) )
12316 return SCIP_OKAY;
12317
12318 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12319 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12320 return SCIP_OKAY;
12321
12322 found = TRUE;
12323
12324 frac += (val - SCIPfloor(scip, val)) * ub;
12325
12326 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12327 * fractional parts of the variables, we cannot tighten the coefficients
12328 *
12329 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12330 * x2-x4 set to 1 would be feasible but not after flooring
12331 */
12332 if( SCIPisGE(scip, frac, 1 + siderest) )
12333 return SCIP_OKAY;
12334 }
12335 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12336 else
12337 return SCIP_OKAY;
12338 }
12339 assert(v == -1);
12340
12341 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12342
12343 /* round lhs and coefficients to integral values */
12344 if( found )
12345 {
12346 for( v = nvars - 1; v >= 0; --v )
12347 {
12348 val = vals[v];
12349
12350 /* add the whole fractional part */
12351 if( !SCIPisIntegral(scip, val) )
12352 {
12353 lb = SCIPvarGetLbGlobal(vars[v]);
12354
12355 if( SCIPisFeasZero(scip, lb) )
12356 newval = SCIPfloor(scip, val);
12357 else
12358 newval = SCIPceil(scip, val);
12359
12360 if( SCIPisZero(scip, newval) )
12361 {
12362 /* delete old redundant coefficient */
12363 SCIP_CALL( delCoefPos(scip, cons, v) );
12364 ++(*nchgcoefs);
12365 }
12366 else
12367 {
12368 /* replace old with new coefficient */
12369 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12370 ++(*nchgcoefs);
12371 }
12372 }
12373 }
12374 }
12375
12376 /* replace old with new left hand side */
12377 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12378 ++(*nchgsides);
12379 }
12380 }
12381
12382 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12383 assert(vars == consdata->vars);
12384 assert(vals == consdata->vals);
12385
12386 if( *infeasible )
12387 return SCIP_OKAY;
12388
12389 rhs = consdata->rhs;
12390 lhs = consdata->lhs;
12391
12392 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12393 assert(!haslhs || !SCIPisNegative(scip, lhs));
12394
12396
12397 nvars = consdata->nvars;
12398 if( nvars < 2 )
12399 return SCIP_OKAY;
12400
12401 allcoefintegral = TRUE;
12402#ifndef NDEBUG
12403 /* debug check if all coefficients are really integral */
12404 for( v = nvars - 1; v >= 0; --v )
12405 assert(SCIPisIntegral(scip, vals[v]));
12406#endif
12407 }
12408
12409 /* @todo following can also work on non integral coefficients, need more investigation */
12410 /* only check constraints with integral coefficients on all integral variables */
12411 if( !allcoefintegral )
12412 return SCIP_OKAY;
12413
12414 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12415 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12416 return SCIP_OKAY;
12417
12418 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12419 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12420 return SCIP_OKAY;
12421
12422 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12423 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12424 return SCIP_OKAY;
12425
12426 assert(nvars >= 2);
12427
12428 /* start gcd procedure for all variables */
12429 do
12430 {
12431 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12432 SCIPdebug( oldnchgsides = *nchgsides; )
12433
12434 /* stop if we have two coeffcients which are one in absolute value */
12435 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12436 return SCIP_OKAY;
12437
12438 gcd = -1;
12439
12440 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12441 * because coefficients of non-binary variables might have changed to zero */
12442 if( !onlybin )
12443 {
12444 foundbin = -1;
12445 onlybin = TRUE;
12446
12447 for( v = nvars - 1; v >= 0; --v )
12448 {
12449 assert(!SCIPisZero(scip, vals[v]));
12450 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12451
12452 if( SCIPvarIsBinary(vars[v]) )
12453 {
12454 if( foundbin == -1 )
12455 foundbin = v;
12456 continue;
12457 }
12458 else
12459 onlybin = FALSE;
12460
12461 absval = REALABS(vals[v]);
12462 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12463 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12464 */
12465 assert(SCIPisFeasIntegral(scip, absval));
12466
12467 if( gcd == -1 )
12468 {
12469 gcd = (SCIP_Longint)(absval + feastol);
12470 assert(gcd >= 1);
12471 }
12472 else
12473 {
12474 /* calculate greatest common divisor for all general variables */
12475 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12476 }
12477 if( gcd == 1 )
12478 break;
12479 }
12480 }
12481 else
12482 foundbin = nvars - 1;
12483
12484 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12485 if( gcd == 1 || foundbin == -1)
12486 return SCIP_OKAY;
12487
12488 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12489
12490 candpos = -1;
12491 candpos2 = -1;
12492
12493 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12494 * change the coefficient
12495 */
12496 for( v = foundbin; v >= 0; --v )
12497 {
12498 if( onlybin || SCIPvarIsBinary(vars[v]) )
12499 {
12500 absval = REALABS(vals[v]);
12501 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12502 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12503 */
12504 assert(SCIPisFeasIntegral(scip, absval));
12505
12506 oldgcd = gcd;
12507
12508 if( gcd == -1 )
12509 {
12510 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12511 assert(gcd >= 1);
12512 }
12513 else
12514 {
12515 /* calculate greatest common divisor for all general and binary variables */
12516 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12517 }
12518
12519 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12520 * can terminate
12521 */
12522 if( gcd == 1 )
12523 {
12524 /* found candidate */
12525 if( candpos == -1 )
12526 {
12527 gcd = oldgcd;
12528 candpos = v;
12529
12530 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12531 * the coefficient change
12532 */
12533 if( onlybin && v == foundbin - 1 )
12534 candpos2 = foundbin;
12535 }
12536 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12537 else
12538 {
12539 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12540 {
12541 assert(candpos2 == nvars - 1);
12542
12543 /* take new candidates */
12544 candpos = candpos2;
12545
12546 /* recalculate gcd from scratch */
12547 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12548 assert(gcd >= 1);
12549
12550 /* calculate greatest common divisor for all general and binary variables */
12551 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12552 if( gcd == 1 )
12553 return SCIP_OKAY;
12554 }
12555 else
12556 /* cannot determine a possible coefficient for reduction */
12557 return SCIP_OKAY;
12558 }
12559 }
12560 }
12561 }
12562 assert(gcd >= 2);
12563
12564 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12565 * further
12566 */
12567 assert(candpos >= 0 && candpos < nvars);
12568
12569 /* all variables and all coefficients are integral, so the side should be too */
12570 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12571
12572 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12573 * @see normalizeCons()
12574 */
12575 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12576 assert(!haslhs || !SCIPisNegative(scip, lhs));
12577
12578 /* determine the remainder of the side and the gcd */
12579 if( hasrhs )
12580 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12581 else
12582 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12583 assert(rest >= 0);
12584 assert(rest < gcd);
12585
12586 /* determine the remainder of the coefficient candidate and the gcd */
12587 if( vals[candpos] < 0 )
12588 {
12589 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12590 assert(restcoef <= -1);
12591 restcoef += gcd;
12592 }
12593 else
12594 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12595 assert(restcoef >= 1);
12596 assert(restcoef < gcd);
12597
12598 if( hasrhs )
12599 {
12600 if( rest > 0 )
12601 {
12602 /* replace old with new right hand side */
12603 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12604 ++(*nchgsides);
12605 }
12606
12607 /* calculate new coefficient */
12608 if( restcoef > rest )
12609 newcoef = vals[candpos] - restcoef + gcd;
12610 else
12611 newcoef = vals[candpos] - restcoef;
12612 }
12613 else
12614 {
12615 if( rest > 0 )
12616 {
12617 /* replace old with new left hand side */
12618 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12619 ++(*nchgsides);
12620 }
12621
12622 /* calculate new coefficient */
12623 if( rest == 0 || restcoef < rest )
12624 newcoef = vals[candpos] - restcoef;
12625 else
12626 newcoef = vals[candpos] - restcoef + gcd;
12627 }
12628 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12629
12630 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));
12631
12632 if( SCIPisZero(scip, newcoef) )
12633 {
12634 /* delete redundant coefficient */
12635 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12636 }
12637 else
12638 {
12639 /* replace old with new coefficient */
12640 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12641 }
12642 ++(*nchgcoefs);
12643
12644 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12645 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12646 assert(vars == consdata->vars);
12647 assert(vals == consdata->vals);
12648
12649 if( *infeasible )
12650 return SCIP_OKAY;
12651
12653
12654 rhs = consdata->rhs;
12655 lhs = consdata->lhs;
12656 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12657 assert(!haslhs || !SCIPisNegative(scip, lhs));
12658
12659 nvars = consdata->nvars;
12660
12661 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));
12662 }
12663 while( nvars >= 2 );
12664
12665 return SCIP_OKAY;
12666}
12667
12668
12669/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12670 * cons0 := a * cons0 + b * cons1,
12671 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12672 * for numerical stability, we will only accept integral a and b;
12673 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12674 * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12675 */
12676static
12678 SCIP* scip, /**< SCIP data structure */
12679 SCIP_CONS* cons0, /**< (in)equality to modify */
12680 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12681 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12682 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12683 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12684 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12685 int nvarscommon, /**< number of variables, that appear in both constraints */
12686 int commonidxweight, /**< variable weight sum of common variables */
12687 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12688 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12689 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12690 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12691 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12692 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12693 )
12694{
12695 SCIP_CONSDATA* consdata0;
12696 SCIP_CONSDATA* consdata1;
12697 SCIP_Real a;
12698 SCIP_Real b;
12699 SCIP_Real aggrcoef;
12700 SCIP_Real scalarsum;
12701 SCIP_Real bestscalarsum;
12702 SCIP_Bool betterscalarsum;
12703 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12704 int varweight;
12705 int nvars;
12706 int bestvarweight;
12707 int bestnvars;
12708 int bestv;
12709 int v;
12710 int i;
12711
12712 assert(scip != NULL);
12713 assert(cons0 != NULL);
12714 assert(cons1 != NULL);
12715 assert(commonidx0 != NULL);
12716 assert(commonidx1 != NULL);
12717 assert(diffidx0minus1 != NULL);
12718 assert(diffidx1minus0 != NULL);
12719 assert(nvarscommon >= 1);
12720 assert(commonidxweight >= nvarscommon);
12721 assert(nchgcoefs != NULL);
12722 assert(aggregated != NULL);
12723
12724 assert(SCIPconsIsActive(cons0));
12725 assert(SCIPconsIsActive(cons1));
12726
12727 *infeasible = FALSE;
12728
12729 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12730
12731 /* cons0 is an (in)equality */
12732 consdata0 = SCIPconsGetData(cons0);
12733 assert(consdata0 != NULL);
12734 assert(consdata0->nvars >= 1);
12735 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12736 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12737
12738 /* cons1 is an equality */
12739 consdata1 = SCIPconsGetData(cons1);
12740 assert(consdata1 != NULL);
12741 assert(consdata1->nvars >= 1);
12742 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12743 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12744
12745 *aggregated = FALSE;
12746
12747 /* search for the best common variable such that
12748 * val1[var] * consdata0 - val0[var] * consdata1
12749 * has least weighted number of variables
12750 */
12751 bestvarweight = commonidxweight + diffidx0minus1weight;
12752 bestnvars = consdata0->nvars;
12753 bestv = -1;
12754 bestscalarsum = 0.0;
12755 commonvarlindependent = TRUE;
12756 for( v = 0; v < nvarscommon; ++v )
12757 {
12758 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12759 a = consdata1->vals[commonidx1[v]];
12760 b = -consdata0->vals[commonidx0[v]];
12761
12762 /* only try aggregation, if coefficients are integral (numerical stability) */
12764 {
12765 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12766 varweight = diffidx0minus1weight + diffidx1minus0weight;
12767 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12768 scalarsum = REALABS(a) + REALABS(b);
12769 betterscalarsum = (scalarsum < bestscalarsum);
12770 for( i = 0; i < nvarscommon
12771 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12772 {
12773 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12774 if( !SCIPisZero(scip, aggrcoef) )
12775 {
12776 varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12777 nvars++;
12778 }
12779 }
12780 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12781 {
12782 bestv = v;
12783 bestvarweight = varweight;
12784 bestnvars = nvars;
12785 bestscalarsum = scalarsum;
12786 }
12787 }
12788
12789 /* update commonvarlindependent flag, if still TRUE:
12790 * 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
12791 */
12792 if( commonvarlindependent && v > 0 )
12793 commonvarlindependent = SCIPisEQ(scip,
12794 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12795 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12796 }
12797
12798 /* if better aggregation was found, create new constraint and delete old one */
12799 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12800 {
12801 SCIP_CONS* newcons;
12802 SCIP_CONSDATA* newconsdata;
12803 SCIP_VAR** newvars;
12804 SCIP_Real* newvals;
12805 SCIP_Real newlhs;
12806 SCIP_Real newrhs;
12807 int newnvars;
12808
12809 if( bestv != -1 )
12810 {
12811 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12812 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12813 {
12814 a = consdata1->vals[commonidx1[bestv]];
12815 b = -consdata0->vals[commonidx0[bestv]];
12816 }
12817 else
12818 {
12819 a = -consdata1->vals[commonidx1[bestv]];
12820 b = consdata0->vals[commonidx0[bestv]];
12821 }
12822 assert(SCIPisIntegral(scip, a));
12823 assert(SCIPisPositive(scip, a));
12824 assert(SCIPisIntegral(scip, b));
12825 assert(!SCIPisZero(scip, b));
12826 }
12827 else
12828 {
12829 assert(commonvarlindependent);
12830 if( consdata1->vals[commonidx1[0]] > 0.0 )
12831 {
12832 a = consdata1->vals[commonidx1[0]];
12833 b = -consdata0->vals[commonidx0[0]];
12834 }
12835 else
12836 {
12837 a = -consdata1->vals[commonidx1[0]];
12838 b = consdata0->vals[commonidx0[0]];
12839 }
12840 assert(SCIPisPositive(scip, a));
12841 assert(!SCIPisZero(scip, b));
12842
12843 /* if a/b is integral, then we can easily choose integer multipliers */
12844 if( SCIPisIntegral(scip, a/b) )
12845 {
12846 if( a/b > 0 )
12847 {
12848 a /= b;
12849 b = 1.0;
12850 }
12851 else
12852 {
12853 a /= -b;
12854 b = -1.0;
12855 }
12856 }
12857
12858 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12859 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12860 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12861 }
12862
12863 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12864 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12865 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12866 SCIPdebugPrintCons(scip, cons0, NULL);
12867 SCIPdebugPrintCons(scip, cons1, NULL);
12868
12869 /* get temporary memory for creating the new linear constraint */
12870 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12871 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12872
12873 /* calculate the common coefficients, if we have not recognized linear dependency */
12874 newnvars = 0;
12875 if( !commonvarlindependent )
12876 {
12877 for( i = 0; i < nvarscommon; ++i )
12878 {
12879 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12880 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12881
12882 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12883 if( !SCIPisZero(scip, aggrcoef) )
12884 {
12885 assert(newnvars < bestnvars);
12886 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12887 newvals[newnvars] = aggrcoef;
12888 newnvars++;
12889 }
12890 }
12891 }
12892 else
12893 {
12894 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12895#ifndef NDEBUG
12896 for( i = 0; i < nvarscommon; ++i )
12897 {
12898 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12899 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12900
12901 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12902 assert(SCIPisZero(scip, aggrcoef));
12903 }
12904#endif
12905 }
12906
12907 /* calculate the coefficients appearing in cons0 but not in cons1 */
12908 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12909 {
12910 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12911
12912 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12913 assert(!SCIPisZero(scip, aggrcoef));
12914 assert(newnvars < bestnvars);
12915 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12916 newvals[newnvars] = aggrcoef;
12917 newnvars++;
12918 }
12919
12920 /* calculate the coefficients appearing in cons1 but not in cons0 */
12921 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12922 {
12923 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12924
12925 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12926 assert(!SCIPisZero(scip, aggrcoef));
12927 assert(newnvars < bestnvars);
12928 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12929 newvals[newnvars] = aggrcoef;
12930 newnvars++;
12931 }
12932 assert(newnvars == bestnvars);
12933
12934 /* calculate the new left and right hand side of the (in)equality */
12935 assert(!SCIPisInfinity(scip, -consdata1->lhs));
12936 assert(!SCIPisInfinity(scip, consdata1->rhs));
12937 if( SCIPisInfinity(scip, -consdata0->lhs) )
12938 newlhs = -SCIPinfinity(scip);
12939 else
12940 newlhs = a * consdata0->lhs + b * consdata1->lhs;
12941 if( SCIPisInfinity(scip, consdata0->rhs) )
12942 newrhs = SCIPinfinity(scip);
12943 else
12944 newrhs = a * consdata0->rhs + b * consdata1->rhs;
12945
12946 /* create the new linear constraint */
12947 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12952
12953 newconsdata = SCIPconsGetData(newcons);
12954 assert(newconsdata != NULL);
12955
12956 /* copy the upgraded flag from the old cons0 to the new constraint */
12957 newconsdata->upgraded = consdata0->upgraded;
12958
12959 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12960
12961 if( *infeasible )
12962 goto TERMINATE;
12963
12964 /* check, if we really want to use the new constraint instead of the old one:
12965 * use the new one, if the maximum norm doesn't grow too much
12966 */
12967 if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12968 {
12969 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12970 SCIPdebugPrintCons(scip, newcons, NULL);
12971
12972 /* update the statistics: we changed all coefficients */
12973 if( !consdata0->upgraded )
12974 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12975 *aggregated = TRUE;
12976
12977 /* delete the old constraint, and add the new linear constraint to the problem */
12978 SCIP_CALL( SCIPdelCons(scip, cons0) );
12979 SCIP_CALL( SCIPaddCons(scip, newcons) );
12980 }
12981
12982 TERMINATE:
12983 /* release the new constraint */
12984 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12985
12986 /* free temporary memory */
12987 SCIPfreeBufferArray(scip, &newvals);
12988 SCIPfreeBufferArray(scip, &newvars);
12989 }
12990
12991 return SCIP_OKAY;
12992}
12993
12994/** gets the key of the given element */
12995static
12996SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12997{ /*lint --e{715}*/
12998 /* the key is the element itself */
12999 return elem;
13000}
13001
13002/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13003 * coefficients are either equal or negated
13004 */
13005static
13006SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
13007{
13008 SCIP* scip;
13009 SCIP_CONSDATA* consdata1;
13010 SCIP_CONSDATA* consdata2;
13011 SCIP_Real minscale;
13012 SCIP_Real maxscale;
13013 int i;
13014
13015 assert(key1 != NULL);
13016 assert(key2 != NULL);
13017 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13018 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13019 assert(consdata1->indexsorted);
13020 assert(consdata2->indexsorted);
13021
13022 scip = (SCIP*)userptr;
13023 assert(scip != NULL);
13024
13025 /* if it is the same constraint we dont need to check anything */
13026 if( key1 == key2 )
13027 return TRUE;
13028
13029 /* checks trivial case */
13030 if( consdata1->nvars != consdata2->nvars )
13031 return FALSE;
13032
13033 /* tests if variables are equal */
13034 for( i = 0; i < consdata1->nvars; ++i )
13035 {
13036 if( consdata1->vars[i] != consdata2->vars[i] )
13037 {
13038 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13039 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13040 return FALSE;
13041 }
13042 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13043 }
13044
13045 /* order by maxabsval */
13046 if( consdataGetMaxAbsval(consdata1) > consdataGetMaxAbsval(consdata2) )
13047 SCIPswapPointers((void**)&consdata1, (void**)&consdata2);
13048
13049 /* initialize extremal scales */
13050 minscale = SCIPinfinity(scip);
13051 maxscale = -SCIPinfinity(scip);
13052
13053 /* test if coefficient scales are equal */
13054 for( i = 0; i < consdata1->nvars; ++i )
13055 {
13056 SCIP_Real scale = consdata2->vals[i] / consdata1->vals[i];
13057
13058 if( minscale > scale )
13059 {
13060 minscale = scale;
13061
13062 if( SCIPisLT(scip, minscale, maxscale) )
13063 return FALSE;
13064 }
13065
13066 if( maxscale < scale )
13067 {
13068 maxscale = scale;
13069
13070 if( SCIPisLT(scip, minscale, maxscale) )
13071 return FALSE;
13072 }
13073 }
13074
13075 return TRUE;
13076}
13077
13078/** returns the hash value of the key */
13079static
13080SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13081{
13082 SCIP_CONSDATA* consdata;
13083 int minidx;
13084 int mididx;
13085 int maxidx;
13086#ifndef NDEBUG
13087 SCIP* scip;
13088
13089 scip = (SCIP*)userptr;
13090 assert(scip != NULL);
13091#endif
13092
13093 assert(key != NULL);
13094 consdata = SCIPconsGetData((SCIP_CONS*)key);
13095 assert(consdata != NULL);
13096 assert(consdata->nvars > 0);
13097
13098 assert(consdata->indexsorted);
13099
13100 minidx = SCIPvarGetIndex(consdata->vars[0]);
13101 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13102 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13103
13104 /* using only the variable indices as hash, since the values are compared by epsilon */
13105 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
13106}
13107
13108/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13109 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13110 */
13111static
13113 SCIP_CONS* cons /**< linear constraint */
13114 )
13115{
13116 SCIP_CONSDATA* consdata;
13117
13118 assert(cons != NULL);
13119
13120 consdata = SCIPconsGetData(cons);
13121 assert(consdata != NULL);
13122
13123 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13124}
13125
13126/** updates the hashtable such that out of all constraints in the hashtable that are detected
13127 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13128 * and all others are removed from the hashtable and stored in the given array
13129 */
13130static
13132 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13133 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13134 * upon return will contain the constraint that should be kept */
13135 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13136 * these constraints where removed from the hashtable */
13137 int* nparallelconss /**< pointer to return number of parallel constraints */
13138 )
13139{
13140 SCIP_CONS* parallelcons;
13141 unsigned int querykey;
13142
13143 *nparallelconss = 0;
13144 querykey = getParallelConsKey(*querycons);
13145
13146 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13147 {
13148 unsigned int conskey = getParallelConsKey(parallelcons);
13149
13150 if( conskey < querykey )
13151 {
13152 parallelconss[(*nparallelconss)++] = *querycons;
13153 *querycons = parallelcons;
13154 querykey = conskey;
13155 }
13156 else
13157 {
13158 parallelconss[(*nparallelconss)++] = parallelcons;
13159 }
13160
13161 /* if the constraint that just came out of the hash table is the one that is kept,
13162 * we do not need to look into the hashtable again, since the invariant is that
13163 * in the hashtable only pair-wise non-parallel constraints are contained.
13164 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13165 * could be contained due to non-transitivity of the equality comparison.
13166 * Also we can return immediately, since parallelcons is already contained in the
13167 * hashtable and we do not need to remove and reinsert it.
13168 */
13169 if( *querycons == parallelcons )
13170 return SCIP_OKAY;
13171
13172 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13173 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13174 }
13175
13176 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13177 * comnpares equal to querycons at this point
13178 */
13179#ifndef NDEBUG
13180 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13181#else
13182 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13183#endif
13184
13185 return SCIP_OKAY;
13186}
13187
13188/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13189 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13190 */
13191static
13193 SCIP* scip, /**< SCIP data structure */
13194 BMS_BLKMEM* blkmem, /**< block memory */
13195 SCIP_CONS** conss, /**< constraint set */
13196 int nconss, /**< number of constraints in constraint set */
13197 int* firstchange, /**< pointer to store first changed constraint */
13198 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13199 int* ndelconss, /**< pointer to count number of deleted constraints */
13200 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13201 )
13202{
13203 SCIP_HASHTABLE* hashtable;
13204 SCIP_CONS** parallelconss;
13205 int nparallelconss;
13206 int hashtablesize;
13207 int c;
13208
13209 assert(scip != NULL);
13210 assert(blkmem != NULL);
13211 assert(conss != NULL);
13212 assert(firstchange != NULL);
13213 assert(cutoff != NULL);
13214 assert(ndelconss != NULL);
13215 assert(nchgsides != NULL);
13216
13217 /* create a hash table for the constraint set */
13218 hashtablesize = nconss;
13219 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13220 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13221
13222 SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13223
13224 /* check all constraints in the given set for redundancy */
13225 for( c = 0; c < nconss; ++c )
13226 {
13227 SCIP_CONS* cons0;
13228 SCIP_CONSDATA* consdata0;
13229
13230 cons0 = conss[c];
13231
13232 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13233 continue;
13234
13235 /* do not check for parallel constraints if they should not be upgraded */
13236 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13237 continue;
13238
13239 /* check for interuption */
13240 if( c % 1000 == 0 && SCIPisStopped(scip) )
13241 break;
13242
13243 /* sorts the constraint */
13244 consdata0 = SCIPconsGetData(cons0);
13245 assert(consdata0 != NULL);
13246 SCIP_CALL( consdataSort(scip, consdata0) );
13247 assert(consdata0->indexsorted);
13248
13249 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13250 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13251 * first variable is positive
13252 * Also inserts cons0 into the hashtable.
13253 */
13254 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13255
13256 if( nparallelconss != 0 )
13257 {
13258 SCIP_Real lhs;
13259 SCIP_Real rhs;
13260
13261 int i;
13262
13263 /* cons0 may have been changed in retrieveParallelConstraints() */
13264 consdata0 = SCIPconsGetData(cons0);
13265
13266 lhs = consdata0->lhs;
13267 rhs = consdata0->rhs;
13268
13269 for( i = 0; i < nparallelconss; ++i )
13270 {
13271 SCIP_CONS* consdel;
13272 SCIP_CONSDATA* consdatadel;
13273 SCIP_Real scale;
13274
13275 consdel = parallelconss[i];
13276 consdatadel = SCIPconsGetData(consdel);
13277
13278 /* do not delete constraint if it should not be upgraded */
13279 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13280 continue;
13281
13282 assert(SCIPconsIsActive(consdel));
13283 assert(!SCIPconsIsModifiable(consdel));
13284
13285 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13286 * delete old constraints afterwards
13287 */
13288 assert(consdatadel != NULL);
13289 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13290
13291 assert(consdatadel->indexsorted);
13292 assert(consdata0->vars[0] == consdatadel->vars[0]);
13293
13294 scale = consdata0->vals[0] / consdatadel->vals[0];
13295 assert(scale != 0.0);
13296
13297 /* in debug mode, check that all coefficients are equal with respect to epsilon
13298 * if the constraints are in equilibrium scale
13299 */
13300#ifndef NDEBUG
13301 {
13302 assert(consdata0->validmaxabsval);
13303 assert(consdatadel->validmaxabsval);
13304 int k;
13305 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13306 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13307
13308 for( k = 0; k < consdata0->nvars; ++k )
13309 {
13310 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13311 }
13312 }
13313#endif
13314
13315 if( scale > 0.0 )
13316 {
13317 /* the coefficients of both constraints are parallel with a positive scale */
13318 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13319 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13320 SCIPdebugPrintCons(scip, cons0, NULL);
13321 SCIPdebugPrintCons(scip, consdel, NULL);
13322
13323 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13324 lhs = MAX(scale * consdatadel->lhs, lhs);
13325
13326 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13327 rhs = MIN(scale * consdatadel->rhs, rhs);
13328 }
13329 else
13330 {
13331 /* the coefficients of both rows are negations */
13332 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13333 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13334 SCIPdebugPrintCons(scip, cons0, NULL);
13335 SCIPdebugPrintCons(scip, consdel, NULL);
13336
13337 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13338 lhs = MAX(scale * consdatadel->rhs, lhs);
13339
13340 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13341 rhs = MIN(scale * consdatadel->lhs, rhs);
13342 }
13343
13344 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13345 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13346
13347 /* delete consdel */
13348 assert( ! consdata0->upgraded || consdatadel->upgraded );
13349 SCIP_CALL( SCIPdelCons(scip, consdel) );
13350 if( !consdatadel->upgraded )
13351 (*ndelconss)++;
13352 }
13353
13354 if( SCIPisFeasLT(scip, rhs, lhs) )
13355 {
13356 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13357 *cutoff = TRUE;
13358 break;
13359 }
13360
13361 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13362 if( lhs > rhs )
13363 {
13364 rhs = (lhs + rhs)/2;
13365 lhs = rhs;
13366 }
13367
13368 /* update lhs and rhs of cons0 */
13369 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13370 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13371
13372 /* update the first changed constraint to begin the next aggregation round with */
13373 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13374 *firstchange = SCIPconsGetPos(cons0);
13375
13376 assert(SCIPconsIsActive(cons0));
13377 }
13378 }
13379#ifdef SCIP_MORE_DEBUG
13380 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13382#endif
13383
13384 SCIPfreeBufferArray(scip, &parallelconss);
13385
13386 /* free hash table */
13387 SCIPhashtableFree(&hashtable);
13388
13389 return SCIP_OKAY;
13390}
13391
13392/** compares constraint with all prior constraints for possible redundancy or aggregation,
13393 * and removes or changes constraint accordingly
13394 */
13395static
13397 SCIP* scip, /**< SCIP data structure */
13398 SCIP_CONS** conss, /**< constraint set */
13399 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13400 int chkind, /**< index of constraint to check against all prior indices upto startind */
13401 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13402 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13403 int* ndelconss, /**< pointer to count number of deleted constraints */
13404 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13405 int* nchgcoefs /**< pointer to count number of changed coefficients */
13406 )
13407{
13408 SCIP_CONS* cons0;
13409 SCIP_CONSDATA* consdata0;
13410 int* commonidx0;
13411 int* commonidx1;
13412 int* diffidx0minus1;
13413 int* diffidx1minus0;
13414 uint64_t possignature0;
13415 uint64_t negsignature0;
13416 SCIP_Bool cons0changed;
13417 SCIP_Bool cons0isequality;
13418 int diffidx1minus0size;
13419 int c;
13420 SCIP_Real cons0lhs;
13421 SCIP_Real cons0rhs;
13422 SCIP_Bool cons0upgraded;
13423
13424 assert(scip != NULL);
13425 assert(conss != NULL);
13426 assert(firstchange <= chkind);
13427 assert(cutoff != NULL);
13428 assert(ndelconss != NULL);
13429 assert(nchgsides != NULL);
13430 assert(nchgcoefs != NULL);
13431
13432 /* get the constraint to be checked against all prior constraints */
13433 cons0 = conss[chkind];
13434 assert(cons0 != NULL);
13435 assert(SCIPconsIsActive(cons0));
13436 assert(!SCIPconsIsModifiable(cons0));
13437
13438 consdata0 = SCIPconsGetData(cons0);
13439 assert(consdata0 != NULL);
13440 assert(consdata0->nvars >= 1);
13441 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13442
13443 /* sort the constraint */
13444 SCIP_CALL( consdataSort(scip, consdata0) );
13445
13446 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13447 consdataCalcSignatures(consdata0);
13448 possignature0 = consdata0->possignature;
13449 negsignature0 = consdata0->negsignature;
13450
13451 /* get temporary memory for indices of common variables */
13452 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13453 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13454 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13455 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13456 diffidx1minus0size = consdata0->nvars;
13457
13458 cons0lhs = consdata0->lhs;
13459 cons0rhs = consdata0->rhs;
13460 cons0upgraded = consdata0->upgraded;
13461
13462 /* check constraint against all prior constraints */
13463 cons0changed = consdata0->changed;
13464 consdata0->changed = FALSE;
13465 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13466 {
13467 SCIP_CONS* cons1;
13468 SCIP_CONSDATA* consdata1;
13469 uint64_t possignature1;
13470 uint64_t negsignature1;
13471 SCIP_Bool cons0dominateslhs;
13472 SCIP_Bool cons1dominateslhs;
13473 SCIP_Bool cons0dominatesrhs;
13474 SCIP_Bool cons1dominatesrhs;
13475 SCIP_Bool cons1isequality;
13476 SCIP_Bool coefsequal;
13477 SCIP_Bool coefsnegated;
13478 SCIP_Bool tryaggregation;
13479 int nvarscommon;
13480 int nvars0minus1;
13481 int nvars1minus0;
13482 int commonidxweight;
13483 int diffidx0minus1weight;
13484 int diffidx1minus0weight;
13485 int v0;
13486 int v1;
13487
13488 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13489 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13490 assert(cons0upgraded == consdata0->upgraded);
13491
13492 cons1 = conss[c];
13493
13494 /* cons1 has become inactive during presolving of constraint pairs */
13495 if( cons1 == NULL )
13496 continue;
13497
13498 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13499 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13500
13501 consdata1 = SCIPconsGetData(cons1);
13502 assert(consdata1 != NULL);
13503
13504 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13505 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13506 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13507
13508 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13509 if( !cons0changed && !consdata1->changed )
13510 continue;
13511
13512 /* if both constraints are already upgraded, skip the pair;
13513 * because changes on these constraints cannot be applied to the instance anymore */
13514 if( cons0upgraded && consdata1->upgraded )
13515 continue;
13516
13517 assert(consdata1->nvars >= 1);
13518
13519 /* sort the constraint */
13520 SCIP_CALL( consdataSort(scip, consdata1) );
13521
13522 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13523 consdataCalcSignatures(consdata1);
13524 possignature1 = consdata1->possignature;
13525 negsignature1 = consdata1->negsignature;
13526
13527 /* the signatures give a quick test to check for domination and equality of coefficients */
13528 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13529 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13530 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13531 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13532 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13533 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13534 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13535 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13536 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13537 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13538 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13539 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13540 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13541 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13542 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13543 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13544 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13545 && !coefsequal && !coefsnegated && !tryaggregation )
13546 continue;
13547
13548 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13549 if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13550 {
13551 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13552 diffidx1minus0size = consdata1->nvars;
13553 }
13554
13555 /* check consdata0 against consdata1:
13556 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13557 * consdata0 dominates consdata1 w.r.t. left hand side
13558 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13559 * consdata0 dominates consdata1 w.r.t. right hand side
13560 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13561 * ranged row (or equality)
13562 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13563 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13564 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13565 * number of continuous and integer variables are preferred:
13566 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13567 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13568 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13569 * to be positive to not switch the sense of the (in)equality cons0
13570 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13571 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13572 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13573 * to be positive to not switch the sense of the (in)equality cons1
13574 */
13575
13576 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13577 nvarscommon = 0;
13578 commonidxweight = 0;
13579 nvars0minus1 = 0;
13580 diffidx0minus1weight = 0;
13581 nvars1minus0 = 0;
13582 diffidx1minus0weight = 0;
13583 v0 = 0;
13584 v1 = 0;
13585 while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13586 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13587 || coefsequal || coefsnegated || tryaggregation) )
13588 {
13589 SCIP_VAR* var;
13590 SCIP_Real val0;
13591 SCIP_Real val1;
13592 int varcmp;
13593
13594 /* test, if variable appears in only one or in both constraints */
13595 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13596 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13597 else if( v0 < consdata0->nvars )
13598 varcmp = -1;
13599 else
13600 varcmp = +1;
13601
13602 switch( varcmp )
13603 {
13604 case -1:
13605 /* variable doesn't appear in consdata1 */
13606 var = consdata0->vars[v0];
13607 val0 = consdata0->vals[v0];
13608 val1 = 0.0;
13609 if( tryaggregation )
13610 {
13611 diffidx0minus1[nvars0minus1] = v0;
13612 nvars0minus1++;
13613 diffidx0minus1weight += getVarWeight(var);
13614 }
13615 v0++;
13616 coefsequal = FALSE;
13617 coefsnegated = FALSE;
13618 break;
13619
13620 case +1:
13621 /* variable doesn't appear in consdata0 */
13622 var = consdata1->vars[v1];
13623 val0 = 0.0;
13624 val1 = consdata1->vals[v1];
13625 if( tryaggregation )
13626 {
13627 diffidx1minus0[nvars1minus0] = v1;
13628 nvars1minus0++;
13629 diffidx1minus0weight += getVarWeight(var);
13630 }
13631 v1++;
13632 coefsequal = FALSE;
13633 coefsnegated = FALSE;
13634 break;
13635
13636 case 0:
13637 /* variable appears in both constraints */
13638 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13639 var = consdata0->vars[v0];
13640 val0 = consdata0->vals[v0];
13641 val1 = consdata1->vals[v1];
13642 if( tryaggregation )
13643 {
13644 commonidx0[nvarscommon] = v0;
13645 commonidx1[nvarscommon] = v1;
13646 nvarscommon++;
13647 commonidxweight += getVarWeight(var);
13648 }
13649 v0++;
13650 v1++;
13651 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13652 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13653 break;
13654
13655 default:
13656 SCIPerrorMessage("invalid comparison result\n");
13657 SCIPABORT();
13658 var = NULL;
13659 val0 = 0.0;
13660 val1 = 0.0;
13661 }
13662 assert(var != NULL);
13663
13664 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13665 if( SCIPisGT(scip, val0, val1) )
13666 {
13668 {
13669 cons0dominatesrhs = FALSE;
13670 cons1dominateslhs = FALSE;
13671 }
13673 {
13674 cons0dominateslhs = FALSE;
13675 cons1dominatesrhs = FALSE;
13676 }
13677 }
13678 else if( SCIPisLT(scip, val0, val1) )
13679 {
13681 {
13682 cons0dominateslhs = FALSE;
13683 cons1dominatesrhs = FALSE;
13684 }
13686 {
13687 cons0dominatesrhs = FALSE;
13688 cons1dominateslhs = FALSE;
13689 }
13690 }
13691 }
13692
13693 /* check for disaggregated ranged rows */
13694 if( coefsequal || coefsnegated )
13695 {
13696 SCIP_CONS* consstay;
13697 SCIP_CONS* consdel;
13698#ifndef NDEBUG
13699 SCIP_CONSDATA* consdatastay;
13700#endif
13701 SCIP_CONSDATA* consdatadel;
13702 SCIP_Real lhs;
13703 SCIP_Real rhs;
13704 int consinddel;
13705
13706 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13707 * best left and right hand sides; delete the old constraints afterwards
13708 */
13709 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13710 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13711 SCIPdebugPrintCons(scip, cons0, NULL);
13712 SCIPdebugPrintCons(scip, cons1, NULL);
13713
13714 if( coefsequal )
13715 {
13716 /* the coefficients of both rows are equal */
13717 lhs = MAX(consdata0->lhs, consdata1->lhs);
13718 rhs = MIN(consdata0->rhs, consdata1->rhs);
13719 }
13720 else
13721 {
13722 /* the coefficients of both rows are negations */
13723 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13724 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13725 }
13726 if( SCIPisFeasLT(scip, rhs, lhs) )
13727 {
13728 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13729 *cutoff = TRUE;
13730 break;
13731 }
13732
13733 /* check which constraint has to stay;
13734 * changes applied to an upgraded constraint will not be considered in the instance */
13735 if( consdata0->upgraded )
13736 {
13737 assert(!consdata1->upgraded);
13738 consstay = cons1;
13739#ifndef NDEBUG
13740 consdatastay = consdata1;
13741#endif
13742
13743 consdel = cons0;
13744 consdatadel = consdata0;
13745 consinddel = chkind;
13746 }
13747 else
13748 {
13749 consstay = cons0;
13750#ifndef NDEBUG
13751 consdatastay = consdata0;
13752#endif
13753
13754 consdel = cons1;
13755 consdatadel = consdata1;
13756 consinddel = c;
13757 }
13758
13759 /* update the sides of consstay */
13760 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13761 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13762 if( !consdata0->upgraded )
13763 {
13764 assert(consstay == cons0);
13765 cons0lhs = consdata0->lhs;
13766 cons0rhs = consdata0->rhs;
13767 }
13768
13769 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13770 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13771
13772 assert( !consdatastay->upgraded );
13773 /* delete consdel */
13774 SCIP_CALL( SCIPdelCons(scip, consdel) );
13775 conss[consinddel] = NULL;
13776 if( !consdatadel->upgraded )
13777 (*ndelconss)++;
13778 continue;
13779 }
13780
13781 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13782 * redundant
13783 */
13784 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13785 {
13786 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13787 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13788 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13789 SCIPdebugPrintCons(scip, cons0, NULL);
13790 SCIPdebugPrintCons(scip, cons1, NULL);
13791
13792 /* check for infeasibility */
13793 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13794 {
13795 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13796 *cutoff = TRUE;
13797 break;
13798 }
13799
13800 /* remove redundant left hand side */
13801 if( !SCIPisInfinity(scip, -consdata0->lhs) )
13802 {
13803 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13804 cons0lhs = consdata0->lhs;
13805 cons0isequality = FALSE;
13806 if( !consdata0->upgraded )
13807 {
13808 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13809 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13810
13811 (*nchgsides)++;
13812 }
13813 }
13814 }
13815 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13816 {
13817 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13818 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13819 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13820 SCIPdebugPrintCons(scip, cons1, NULL);
13821 SCIPdebugPrintCons(scip, cons0, NULL);
13822
13823 /* check for infeasibility */
13824 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13825 {
13826 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13827 *cutoff = TRUE;
13828 break;
13829 }
13830
13831 /* remove redundant left hand side */
13832 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13833 {
13834 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13835 cons1isequality = FALSE;
13836 if( !consdata1->upgraded )
13837 {
13838 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13839 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13840
13841 (*nchgsides)++;
13842 }
13843 }
13844 }
13845 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13846 {
13847 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13848 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13849 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13850 SCIPdebugPrintCons(scip, cons0, NULL);
13851 SCIPdebugPrintCons(scip, cons1, NULL);
13852
13853 /* check for infeasibility */
13854 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13855 {
13856 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13857 *cutoff = TRUE;
13858 break;
13859 }
13860
13861 /* remove redundant right hand side */
13862 if( !SCIPisInfinity(scip, consdata0->rhs) )
13863 {
13864 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13865 cons0rhs = consdata0->rhs;
13866 cons0isequality = FALSE;
13867 if( !consdata0->upgraded )
13868 {
13869 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13870 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13871
13872 (*nchgsides)++;
13873 }
13874 }
13875 }
13876 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13877 {
13878 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13879 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13880 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13881 SCIPdebugPrintCons(scip, cons1, NULL);
13882 SCIPdebugPrintCons(scip, cons0, NULL);
13883
13884 /* check for infeasibility */
13885 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13886 {
13887 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13888 *cutoff = TRUE;
13889 break;
13890 }
13891
13892 /* remove redundant right hand side */
13893 if( !SCIPisInfinity(scip, consdata1->rhs) )
13894 {
13895 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13896 cons1isequality = FALSE;
13897 if( !consdata1->upgraded )
13898 {
13899 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13900 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13901
13902 (*nchgsides)++;
13903 }
13904 }
13905 }
13906
13907 /* check for now redundant constraints */
13908 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13909 {
13910 /* consdata0 became redundant */
13911 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13912 SCIP_CALL( SCIPdelCons(scip, cons0) );
13913 conss[chkind] = NULL;
13914 if( !consdata0->upgraded )
13915 {
13916 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13917 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13918
13919 (*ndelconss)++;
13920 }
13921 continue;
13922 }
13923 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13924 {
13925 /* consdata1 became redundant */
13926 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13927 SCIP_CALL( SCIPdelCons(scip, cons1) );
13928 conss[c] = NULL;
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 (*ndelconss)++;
13935 }
13936 continue;
13937 }
13938
13939 /* check, if we want to aggregate an (in)equality with an equality:
13940 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13941 */
13942 if( tryaggregation )
13943 {
13944 SCIP_Bool aggregated;
13945
13946 assert(consdata0->nvars == nvarscommon + nvars0minus1);
13947 assert(consdata1->nvars == nvarscommon + nvars1minus0);
13948
13949 aggregated = FALSE;
13950 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13951 {
13952 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13953 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13954 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13955 nchgcoefs, &aggregated, cutoff) );
13956
13957 if( *cutoff )
13958 break;
13959
13960 /* update array of active constraints */
13961 if( aggregated )
13962 {
13963 assert(!SCIPconsIsActive(cons0));
13964 assert(SCIPconsIsActive(cons1));
13965 conss[chkind] = NULL;
13966 }
13967 }
13968 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13969 {
13970 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13971 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13972 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13973 nchgcoefs, &aggregated, cutoff) );
13974
13975 if( *cutoff )
13976 break;
13977
13978 /* update array of active constraints */
13979 if( aggregated )
13980 {
13981 assert(!SCIPconsIsActive(cons1));
13982 assert(SCIPconsIsActive(cons0));
13983 conss[c] = NULL;
13984 }
13985 }
13986 }
13987 }
13988
13989 /* free temporary memory */
13990 SCIPfreeBufferArray(scip, &diffidx1minus0);
13991 SCIPfreeBufferArray(scip, &diffidx0minus1);
13992 SCIPfreeBufferArray(scip, &commonidx1);
13993 SCIPfreeBufferArray(scip, &commonidx0);
13994
13995 return SCIP_OKAY;
13996}
13997
13998/** do stuffing presolving on a single constraint */
13999static
14001 SCIP* scip, /**< SCIP data structure */
14002 SCIP_CONS* cons, /**< linear constraint */
14003 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14004 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14005 * constraints using the cheapest variable? */
14006 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14007 int* nfixedvars, /**< pointer to count the total number of fixed variables */
14008 int* nchgbds /**< pointer to count the total number of tightened bounds */
14009 )
14010{
14011 SCIP_CONSDATA* consdata;
14012 SCIP_Real* ratios;
14013 int* varpos;
14014 SCIP_Bool* swapped;
14015 SCIP_VAR** vars;
14016 SCIP_Real* vals;
14017 SCIP_VAR* var;
14018 SCIP_Real lb;
14019 SCIP_Real ub;
14020 SCIP_Real minactivity;
14021 SCIP_Real maxactivity;
14022 SCIP_Real maxcondactivity;
14023 SCIP_Real mincondactivity;
14024 SCIP_Real rhs;
14025 SCIP_Real val;
14026 SCIP_Real obj;
14027 SCIP_Real factor;
14028 SCIP_Bool isminacttight;
14029 SCIP_Bool ismaxacttight;
14030 SCIP_Bool isminsettoinfinity;
14031 SCIP_Bool ismaxsettoinfinity;
14032 SCIP_Bool tryfixing;
14033 int nsingletons;
14034 int idx;
14035 int v;
14036 int nvars;
14037
14038 assert(scip != NULL);
14039 assert(cons != NULL);
14040 assert(nfixedvars != NULL);
14041
14042 consdata = SCIPconsGetData(cons);
14043
14044 /* we only want to run for inequalities */
14045 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14046 return SCIP_OKAY;
14047
14048 if( singlevarstuffing )
14049 {
14050 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
14051 &isminsettoinfinity, &ismaxsettoinfinity);
14052 }
14053 else
14054 {
14055 minactivity = SCIP_INVALID;
14056 maxactivity = SCIP_INVALID;
14057 isminsettoinfinity = FALSE;
14058 ismaxsettoinfinity = FALSE;
14059 }
14060
14061 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14062 * the new maxactivity is minus the old minactivity then
14063 */
14064 if( SCIPisInfinity(scip, consdata->rhs) )
14065 {
14066 rhs = -consdata->lhs;
14067 factor = -1.0;
14068 maxactivity = -minactivity;
14069 ismaxsettoinfinity = isminsettoinfinity;
14070 }
14071 else
14072 {
14073 assert(SCIPisInfinity(scip, -consdata->lhs));
14074 rhs = consdata->rhs;
14075 factor = 1.0;
14076 }
14077
14078 nvars = consdata->nvars;
14079 vars = consdata->vars;
14080 vals = consdata->vals;
14081
14082 /* check for continuous singletons */
14083 if( singletonstuffing )
14084 {
14085 for( v = 0; v < nvars; ++v )
14086 {
14087 var = vars[v];
14088
14091 break;
14092 }
14093 }
14094 else
14095 /* we don't want to go into the next block */
14096 v = nvars;
14097
14098 /* a singleton was found -> perform singleton variable stuffing */
14099 if( v < nvars )
14100 {
14101 assert(singletonstuffing);
14102
14103 SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14104 SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14105 SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14106
14107 tryfixing = TRUE;
14108 nsingletons = 0;
14109 mincondactivity = 0.0;
14110 maxcondactivity = 0.0;
14111
14112 for( v = 0; v < nvars; ++v )
14113 {
14114 var = vars[v];
14115 lb = SCIPvarGetLbGlobal(var);
14116 ub = SCIPvarGetUbGlobal(var);
14117 obj = SCIPvarGetObj(var);
14118 val = factor * vals[v];
14119
14120 assert(!SCIPisZero(scip, val));
14121
14122 /* the variable is a singleton and continuous */
14125 {
14126 if( SCIPisNegative(scip, obj) && val > 0 )
14127 {
14128 /* case 1: obj < 0 and coef > 0 */
14129 if( SCIPisInfinity(scip, -lb) )
14130 {
14131 tryfixing = FALSE;
14132 break;
14133 }
14134
14135 maxcondactivity += val * lb;
14136 mincondactivity += val * lb;
14137 swapped[v] = FALSE;
14138 ratios[nsingletons] = obj / val;
14139 varpos[nsingletons] = v;
14140 nsingletons++;
14141 }
14142 else if( SCIPisPositive(scip, obj) && val < 0 )
14143 {
14144 /* case 2: obj > 0 and coef < 0 */
14145 if( SCIPisInfinity(scip, ub) )
14146 {
14147 tryfixing = FALSE;
14148 break;
14149 }
14150 /* multiply column by (-1) to become case 1.
14151 * now bounds are swapped: ub := -lb, lb := -ub
14152 */
14153
14154 maxcondactivity += val * ub;
14155 mincondactivity += val * ub;
14156 swapped[v] = TRUE;
14157 ratios[nsingletons] = obj / val;
14158 varpos[nsingletons] = v;
14159 nsingletons++;
14160 }
14161 else if( val > 0 )
14162 {
14163 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14164 * we only consider the lower bound for the constants
14165 */
14166 assert(!SCIPisNegative(scip, obj));
14167
14168 if( SCIPisInfinity(scip, -lb) )
14169 {
14170 /* maybe unbounded */
14171 tryfixing = FALSE;
14172 break;
14173 }
14174
14175 maxcondactivity += val * lb;
14176 mincondactivity += val * lb;
14177 }
14178 else
14179 {
14180 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14181 * we only consider the upper bound for the constants
14182 */
14183 assert(!SCIPisPositive(scip, obj));
14184 assert(val < 0);
14185
14186 if( SCIPisInfinity(scip, ub) )
14187 {
14188 /* maybe unbounded */
14189 tryfixing = FALSE;
14190 break;
14191 }
14192
14193 maxcondactivity += val * ub;
14194 mincondactivity += val * ub;
14195 }
14196 }
14197 else
14198 {
14199 /* consider contribution of discrete variables, non-singleton
14200 * continuous variables and variables with more than one lock
14201 */
14202 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14203 {
14204 tryfixing = FALSE;
14205 break;
14206 }
14207
14208 if( val > 0 )
14209 {
14210 maxcondactivity += val * ub;
14211 mincondactivity += val * lb;
14212 }
14213 else
14214 {
14215 maxcondactivity += val * lb;
14216 mincondactivity += val * ub;
14217 }
14218 }
14219 }
14220 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14221 {
14222 SCIP_Real delta;
14223 SCIP_Bool tightened;
14224#ifdef SCIP_DEBUG
14225 int oldnfixedvars = *nfixedvars;
14226 int oldnchgbds = *nchgbds;
14227#endif
14228
14229 SCIPsortRealInt(ratios, varpos, nsingletons);
14230
14231 /* verify which singleton continuous variables can be fixed */
14232 for( v = 0; v < nsingletons; ++v )
14233 {
14234 idx = varpos[v];
14235 var = vars[idx];
14236 val = factor * vals[idx];
14237 lb = SCIPvarGetLbGlobal(var);
14238 ub = SCIPvarGetUbGlobal(var);
14239
14240 assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14241 assert((val < 0) == swapped[idx]);
14242 val = REALABS(val);
14243
14244 /* stop fixing if variable bounds are not finite */
14245 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14246 break;
14247
14251
14252 /* calculate the change in the row activities if this variable changes
14253 * its value from its worst to its best bound
14254 */
14255 if( swapped[idx] )
14256 delta = -(lb - ub) * val;
14257 else
14258 delta = (ub - lb) * val;
14259
14260 assert(!SCIPisNegative(scip, delta));
14261
14262 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14263 {
14264 if( swapped[idx] )
14265 {
14266 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14267 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14268 }
14269 else
14270 {
14271 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14272 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14273 }
14274
14275 if( *cutoff )
14276 break;
14277 if( tightened )
14278 {
14279 (*nfixedvars)++;
14280 }
14281 }
14282 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14283 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14284 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14285 * troubles in case of large bounds.
14286 */
14287 else if( SCIPisLE(scip, rhs, mincondactivity) )
14288 {
14289 if( swapped[idx] )
14290 {
14291 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14292 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14293 }
14294 else
14295 {
14296 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14297 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14298 }
14299
14300 if( *cutoff )
14301 break;
14302 if( tightened )
14303 {
14304 (*nfixedvars)++;
14305 }
14306 }
14307
14308 maxcondactivity += delta;
14309 mincondactivity += delta;
14310 }
14311
14312#ifdef SCIP_DEBUG
14313 if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14314 {
14315 SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14316 }
14317#endif
14318 }
14319
14320 SCIPfreeBufferArray(scip, &swapped);
14321 SCIPfreeBufferArray(scip, &ratios);
14322 SCIPfreeBufferArray(scip, &varpos);
14323 }
14324
14325 /* perform single-variable stuffing:
14326 * for a linear inequality
14327 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14328 * with a_i > 0 and objective coefficients c_i < 0,
14329 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14330 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14331 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14332 * is redundant.
14333 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14334 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14335 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14336 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14337 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14338 * upper bound.
14339 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14340 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14341 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14342 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14343 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14344 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14345 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14346 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14347 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14348 * c_k * ceil((maxactivity - rhs)/val) is still better than
14349 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14350 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14351 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14352 * sign of coefficients in constraint and objective prevent the use of this method.
14353 */
14354 if( singlevarstuffing && !ismaxsettoinfinity )
14355 {
14356 SCIP_Real bestratio = -SCIPinfinity(scip);
14357 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14358 SCIP_Real ratio;
14359 int bestindex = -1;
14360 int bestuplocks = 0;
14361 int bestdownlocks = 1;
14362 int downlocks;
14363 int uplocks;
14364 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14365 SCIPdebug( int oldnchgbds = *nchgbds; )
14366
14367 /* loop over all variables to identify the best and second-best ratio */
14368 for( v = 0; v < nvars; ++v )
14369 {
14370 var = vars[v];
14371 obj = SCIPvarGetObj(var);
14372 val = factor * vals[v];
14373
14374 assert(!SCIPisZero(scip, val));
14375
14376 ratio = obj / val;
14377
14378 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14379 if( !SCIPisNegative(scip, ratio) )
14380 {
14381 bestindex = -1;
14382 break;
14383 }
14384
14385 if( val > 0 )
14386 {
14389 }
14390 else
14391 {
14394 }
14395
14396 /* better ratio, update best candidate
14397 * @todo use some tolerance
14398 * @todo check size of domain and updated ratio for integer variables already?
14399 */
14400 if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14401 || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14403 {
14404 /* best index becomes second-best*/
14405 if( bestindex != -1 )
14406 {
14407 /* second-best index must not have more than 1 uplock */
14408 if( bestuplocks > 1 )
14409 {
14410 bestindex = -1;
14411 break;
14412 }
14413 else
14414 {
14415 secondbestratio = bestratio;
14416 }
14417 }
14418 bestdownlocks = downlocks;
14419 bestuplocks = uplocks;
14420 bestratio = ratio;
14421 bestindex = v;
14422
14423 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14424 * if it is not the best, it has too many uplocks -> not applicable
14425 */
14426 if( bestdownlocks > 0 && bestuplocks > 1 )
14427 {
14428 bestindex = -1;
14429 break;
14430 }
14431 }
14432 else
14433 {
14434 /* non-best index must not have more than 1 uplock */
14435 if( uplocks > 1 )
14436 {
14437 bestindex = -1;
14438 break;
14439 }
14440 /* update second-best ratio */
14441 if( ratio > secondbestratio )
14442 {
14443 secondbestratio = ratio;
14444 }
14445 }
14446 }
14447
14448 /* check if we can apply single variable stuffing */
14449 if( bestindex != -1 && bestdownlocks == 0 )
14450 {
14451 SCIP_Bool tightened = FALSE;
14452 SCIP_Real bounddelta;
14453
14454 var = vars[bestindex];
14455 obj = SCIPvarGetObj(var);
14456 val = factor * vals[bestindex];
14457 lb = SCIPvarGetLbGlobal(var);
14458 ub = SCIPvarGetUbGlobal(var);
14459 tryfixing = TRUE;
14460
14461 if( val < 0 )
14462 {
14463 assert(!SCIPisNegative(scip, obj));
14464
14465 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14466 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14467 {
14468 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14469 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14470 assert(SCIPisPositive(scip, activitydelta));
14471
14472 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14473
14474 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14475 assert(SCIPisPositive(scip, bounddelta));
14476 }
14477 else
14478 bounddelta = (maxactivity - rhs)/-val;
14479
14480 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14481
14482 if( tryfixing )
14483 {
14485
14486 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14487 {
14488 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14489 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14490 }
14491 else
14492 {
14493 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14494 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14495 }
14496 }
14497 }
14498 else
14499 {
14500 assert(!SCIPisPositive(scip, obj));
14501
14502 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14503 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14504 {
14505 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14506 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14507 assert(SCIPisPositive(scip, activitydelta));
14508
14509 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14510
14511 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14512 assert(SCIPisPositive(scip, bounddelta));
14513 }
14514 else
14515 bounddelta = (maxactivity - rhs)/val;
14516
14517 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14518
14519 if( tryfixing )
14520 {
14522
14523 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14524 {
14525 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14526 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14527 }
14528 else
14529 {
14530 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14531 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14532 }
14533 }
14534 }
14535
14536 if( *cutoff )
14537 return SCIP_OKAY;
14538 if( tightened )
14539 {
14541 ++(*nfixedvars);
14542 else
14543 ++(*nchgbds);
14544
14545 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14546 for( v = 0; v < nvars; ++v )
14547 {
14548 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14549 SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14552 SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14553 }
14554 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14555
14556 for( v = 0; v < nvars; ++v )
14557 {
14558 if( v == bestindex )
14559 continue;
14560
14561 if( factor * vals[v] < 0 )
14562 {
14563 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14564 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14565 SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14566 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14567 }
14568 else
14569 {
14570 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14571 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14572 SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14573 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14574 }
14575
14576 if( *cutoff )
14577 return SCIP_OKAY;
14578 if( tightened )
14579 ++(*nfixedvars);
14580 }
14581 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14582 }
14583 }
14584 }
14585
14586 return SCIP_OKAY;
14587}
14588
14589/** applies full dual presolving on variables that only appear in linear constraints */
14590static
14592 SCIP* scip, /**< SCIP data structure */
14593 SCIP_CONS** conss, /**< constraint set */
14594 int nconss, /**< number of constraints */
14595 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14596 int* nchgbds, /**< pointer to count the number of bound changes */
14597 int* nchgvartypes /**< pointer to count the number of variable type changes */
14598 )
14599{
14600 SCIP_Real* redlb;
14601 SCIP_Real* redub;
14602 int* nlocksdown;
14603 int* nlocksup;
14604 SCIP_Bool* isimplint;
14605 SCIP_VAR** origvars;
14606 SCIP_VAR** vars;
14607 SCIP_VAR** conscontvars;
14608 int nvars;
14609 int nbinvars;
14610 int nintvars;
14611 int ncontvars;
14612 int v;
14613 int c;
14614
14615 /* we calculate redundancy bounds with the following meaning:
14616 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14617 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14618 * then:
14619 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14620 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14621 */
14622
14623 /* Additionally, we detect continuous variables that are implicitly integral.
14624 * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14625 * and all constraints (including the bounds as trivial constraints) in which:
14626 * c_j > 0: the variable is down-locked,
14627 * c_j < 0: the variable is up-locked,
14628 * c_j = 0: the variable appears
14629 * have, apart from j, only integer variables with integral coefficients and integral sides.
14630 * This is because then, the value of the variable is either determined by one of its bounds or
14631 * by one of these constraints, and in all cases, the value of the variable is integral.
14632 */
14633
14634 assert(scip != NULL);
14635 assert(nconss == 0 || conss != NULL);
14636 assert(nchgbds != NULL);
14637 assert(!SCIPinProbing(scip));
14638
14639 /* get active variables */
14640 nvars = SCIPgetNVars(scip);
14641 origvars = SCIPgetVars(scip);
14642
14643 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14644 nbinvars = SCIPgetNBinVars(scip);
14645 if( nbinvars == nvars )
14646 return SCIP_OKAY;
14647
14648 /* get number of continuous variables */
14649 ncontvars = SCIPgetNContVars(scip);
14650 nintvars = nvars - ncontvars;
14651
14652 /* copy the variable array since this array might change during the curse of this algorithm */
14653 nvars = nvars - nbinvars;
14654 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14655
14656 /* allocate temporary memory */
14657 SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14658 SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14659 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14660 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14661 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14662 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14663
14664 /* initialize redundancy bounds */
14665 for( v = 0; v < nvars; ++v )
14666 {
14667 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14668 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14669 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14670 }
14671 BMSclearMemoryArray(nlocksdown, nvars);
14672 BMSclearMemoryArray(nlocksup, nvars);
14673
14674 /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14675 * We better not use SCIPisFeasIntegral() in these checks.
14676 */
14677 for( v = 0; v < ncontvars; v++ )
14678 {
14679 SCIP_VAR* var;
14680 SCIP_Real obj;
14681 SCIP_Real lb;
14682 SCIP_Real ub;
14683
14684 var = vars[v + nintvars - nbinvars];
14685 lb = SCIPvarGetLbGlobal(var);
14686 ub = SCIPvarGetUbGlobal(var);
14687
14688 obj = SCIPvarGetObj(var);
14689 if( SCIPisZero(scip, obj) )
14690 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14691 else
14692 {
14693 if( SCIPisPositive(scip, obj) )
14694 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14695 else
14696 {
14697 assert(SCIPisNegative(scip, obj));
14698 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14699 }
14700 }
14701 }
14702
14703 /* scan all constraints */
14704 for( c = 0; c < nconss; ++c )
14705 {
14706 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14707 * part of checked disjunctions)
14708 */
14709 if( SCIPconsIsLocked(conss[c]) )
14710 {
14711 SCIP_CONSDATA* consdata;
14712 SCIP_Bool lhsexists;
14713 SCIP_Bool rhsexists;
14714 SCIP_Bool hasimpliedpotential;
14715 SCIP_Bool integralcoefs;
14716 int nlockspos;
14717 int contvarpos;
14718 int nconscontvars;
14719 int i;
14720
14721 consdata = SCIPconsGetData(conss[c]);
14722 assert(consdata != NULL);
14723
14724 /* get number of times the constraint was locked */
14725 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14726
14727 /* we do not want to include constraints with locked negation (this would be too weird) */
14728 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14729 {
14730 /* mark all continuous variables as not being implicit integral */
14731 for( i = 0; i < consdata->nvars; ++i )
14732 {
14733 SCIP_VAR* var;
14734
14735 var = consdata->vars[i];
14737 {
14738 int contv;
14739 contv = SCIPvarGetProbindex(var) - nintvars;
14740 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14741 isimplint[contv] = FALSE;
14742 }
14743 }
14744 continue;
14745 }
14746
14747 /* check for existing sides */
14748 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14749 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14750
14751 /* count locks and update redundancy bounds */
14752 contvarpos = -1;
14753 nconscontvars = 0;
14754 hasimpliedpotential = FALSE;
14755 integralcoefs = !SCIPconsIsModifiable(conss[c]);
14756
14757 for( i = 0; i < consdata->nvars; ++i )
14758 {
14759 SCIP_VAR* var;
14760 SCIP_Real val;
14761 SCIP_Real minresactivity;
14762 SCIP_Real maxresactivity;
14763 SCIP_Real newredlb;
14764 SCIP_Real newredub;
14765 SCIP_Bool ismintight;
14766 SCIP_Bool ismaxtight;
14767 SCIP_Bool isminsettoinfinity;
14768 SCIP_Bool ismaxsettoinfinity;
14769 int arrayindex;
14770
14771 var = consdata->vars[i];
14772 assert(var != NULL);
14773 val = consdata->vals[i];
14774 assert(!SCIPisZero(scip, val));
14775
14776 /* check if still all integer variables have integral coefficients */
14777 if( SCIPvarIsIntegral(var) )
14778 integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14779
14780 /* we do not need to process binary variables */
14781 if( SCIPvarIsBinary(var) )
14782 continue;
14783
14784 if( SCIPconsIsModifiable(conss[c]) )
14785 {
14786 minresactivity = -SCIPinfinity(scip);
14787 maxresactivity = SCIPinfinity(scip);
14788 isminsettoinfinity = TRUE;
14789 ismaxsettoinfinity = TRUE;
14790 }
14791 else
14792 {
14793 /* calculate residual activity bounds if variable would be fixed to zero */
14794 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14795 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
14796
14797 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14798 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14799 * This is needed, because we do not want to rely on relaxed finite resactivities.
14800 */
14801 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
14802
14803 /* check minresactivity for reliability */
14804 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14805 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14806
14807 /* check maxresactivity for reliability */
14808 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14809 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14810 }
14811
14812 arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14813
14814 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14815
14816 newredlb = redlb[arrayindex];
14817 newredub = redub[arrayindex];
14818 if( val > 0.0 )
14819 {
14820 if( lhsexists )
14821 {
14822 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14823 nlocksdown[arrayindex] += nlockspos;
14824 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14825 }
14826 if( rhsexists )
14827 {
14828 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14829 nlocksup[arrayindex] += nlockspos;
14830 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14831 }
14832 }
14833 else
14834 {
14835 if( lhsexists )
14836 {
14837 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14838 nlocksup[arrayindex] += nlockspos;
14839 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14840 }
14841 if( rhsexists )
14842 {
14843 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14844 nlocksdown[arrayindex] += nlockspos;
14845 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14846 }
14847 }
14848
14849 /* if the variable is integer, we have to round the value to the next integral value */
14850 if( SCIPvarIsIntegral(var) )
14851 {
14852 if( !SCIPisInfinity(scip, newredlb) )
14853 newredlb = SCIPceil(scip, newredlb);
14854 if( !SCIPisInfinity(scip, -newredub) )
14855 newredub = SCIPfloor(scip, newredub);
14856 }
14857
14858 /* update redundancy bounds */
14859 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14860 redub[arrayindex] = MIN(redub[arrayindex], newredub);
14861
14862 /* collect the continuous variables of the constraint */
14864 {
14865 int contv;
14866
14867 assert(nconscontvars < ncontvars);
14868 contvarpos = i;
14869 conscontvars[nconscontvars] = var;
14870 nconscontvars++;
14871
14872 contv = SCIPvarGetProbindex(var) - nintvars;
14873 assert(0 <= contv && contv < ncontvars);
14874 hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14875 }
14876 }
14877
14878 /* update implicit integer status of continuous variables */
14879 if( hasimpliedpotential )
14880 {
14881 if( nconscontvars > 1 || !integralcoefs )
14882 {
14883 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14884 * none of the continuous variables is implicit integer
14885 */
14886 for( i = 0; i < nconscontvars; i++ )
14887 {
14888 int contv;
14889 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14890 assert(0 <= contv && contv < ncontvars);
14891 isimplint[contv] = FALSE;
14892 }
14893 }
14894 else
14895 {
14896 SCIP_VAR* var;
14897 SCIP_Real val;
14898 SCIP_Real absval;
14899 int contv;
14900
14901 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14902 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14903 * side(s) of the constraint is integral
14904 */
14905 assert(nconscontvars == 1);
14906 assert(0 <= contvarpos && contvarpos < consdata->nvars);
14907 var = consdata->vars[contvarpos];
14908 val = consdata->vals[contvarpos];
14909 contv = SCIPvarGetProbindex(var) - nintvars;
14910 assert(0 <= contv && contv < ncontvars);
14911 assert(isimplint[contv]);
14912
14913 absval = REALABS(val);
14914 if( !SCIPisEQ(scip, absval, 1.0) )
14915 isimplint[contv] = FALSE;
14916 else
14917 {
14918 SCIP_Real obj;
14919
14920 obj = SCIPvarGetObj(var);
14921 if( obj * val >= 0.0 && lhsexists )
14922 {
14923 /* the variable may be blocked by the constraint's left hand side */
14924 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14925 }
14926 if( obj * val <= 0.0 && rhsexists )
14927 {
14928 /* the variable may be blocked by the constraint's left hand side */
14929 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14930 }
14931 }
14932 }
14933 }
14934 }
14935 }
14936
14937 /* check if any bounds can be tightened due to optimality */
14938 for( v = 0; v < nvars; ++v )
14939 {
14940 SCIP_VAR* var;
14941 SCIP_Real obj;
14942 SCIP_Bool infeasible;
14943 SCIP_Bool tightened;
14944
14945 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14946 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14947 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14948
14949 var = vars[v];
14950 obj = SCIPvarGetObj(var);
14951 if( !SCIPisPositive(scip, -obj) )
14952 {
14953 /* making the variable as small as possible does not increase the objective:
14954 * check if all down locks of the variables are due to linear constraints;
14955 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
14956 * constraints redundant is huge, we better do nothing for numerical reasons
14957 */
14959 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
14960 && !SCIPisHugeValue(scip, -redlb[v])
14961 && redlb[v] < SCIPvarGetUbGlobal(var) )
14962 {
14963 SCIP_Real ub;
14964
14965 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14966 * -> tighten upper bound to x_v <= redlb[v]
14967 */
14968 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14970 redlb[v]);
14971 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14972 assert(!infeasible);
14973
14974 ub = SCIPvarGetUbGlobal(var);
14975 redub[v] = MIN(redub[v], ub);
14976 if( tightened )
14977 (*nchgbds)++;
14978 }
14979 }
14980 if( !SCIPisPositive(scip, obj) )
14981 {
14982 /* making the variable as large as possible does not increase the objective:
14983 * check if all up locks of the variables are due to linear constraints;
14984 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
14985 * constraints redundant is huge, we better do nothing for numerical reasons
14986 */
14988 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
14989 && !SCIPisHugeValue(scip, redub[v])
14990 && redub[v] > SCIPvarGetLbGlobal(var) )
14991 {
14992 SCIP_Real lb;
14993
14994 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14995 * -> tighten lower bound to x_v >= redub[v]
14996 */
14997 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14999 redub[v]);
15000 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15001 assert(!infeasible);
15002
15003 lb = SCIPvarGetLbGlobal(var);
15004 redlb[v] = MAX(redlb[v], lb);
15005 if( tightened )
15006 (*nchgbds)++;
15007 }
15008 }
15009 }
15010
15011 /* upgrade continuous variables to implicit integers */
15012 for( v = nintvars - nbinvars; v < nvars; ++v )
15013 {
15014 SCIP_VAR* var;
15015 SCIP_Bool infeasible;
15016
15017 var = vars[v];
15018 assert(var != NULL);
15019
15021 assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15022 assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15023 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15024
15025 /* we can only conclude implicit integrality if the variable appears in no other constraint */
15026 if( isimplint[v - nintvars + nbinvars]
15027 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15028 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15029 {
15030 /* since we locally copied the variable array we can change the variable type immediately */
15031 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15032 (*nchgvartypes)++;
15033 if( infeasible )
15034 {
15035 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15036 *cutoff = TRUE;
15037
15038 break;
15039 }
15040
15041 SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15043 }
15044 }
15045
15046 /* free temporary memory */
15047 SCIPfreeBufferArray(scip, &conscontvars);
15048 SCIPfreeBufferArray(scip, &isimplint);
15049 SCIPfreeBufferArray(scip, &nlocksup);
15050 SCIPfreeBufferArray(scip, &nlocksdown);
15051 SCIPfreeBufferArray(scip, &redub);
15052 SCIPfreeBufferArray(scip, &redlb);
15053
15054 SCIPfreeBufferArray(scip, &vars);
15055
15056 return SCIP_OKAY;
15057}
15058
15059/** helper function to enforce constraints */
15060static
15062 SCIP* scip, /**< SCIP data structure */
15063 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15064 SCIP_CONS** conss, /**< constraints to process */
15065 int nconss, /**< number of constraints */
15066 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15067 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15068 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15069 )
15070{
15071 SCIP_CONSHDLRDATA* conshdlrdata;
15072 SCIP_Bool checkrelmaxabs;
15073 SCIP_Bool violated;
15074 SCIP_Bool cutoff = FALSE;
15075 int c;
15076
15077 assert(scip != NULL);
15078 assert(conshdlr != NULL);
15079 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15080 assert(result != NULL);
15081
15082 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15083 assert(conshdlrdata != NULL);
15084
15085 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15086
15087 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15088
15089 /* check for violated constraints
15090 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15091 */
15092 *result = SCIP_FEASIBLE;
15093
15094 /* check all useful linear constraints for feasibility */
15095 for( c = 0; c < nusefulconss; ++c )
15096 {
15097 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15098
15099 if( violated )
15100 {
15101 /* insert LP row as cut */
15102 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15103 if ( cutoff )
15104 *result = SCIP_CUTOFF;
15105 else
15106 *result = SCIP_SEPARATED;
15107 }
15108 }
15109
15110 /* check all obsolete linear constraints for feasibility */
15111 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15112 {
15113 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15114
15115 if( violated )
15116 {
15117 /* insert LP row as cut */
15118 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15119 if ( cutoff )
15120 *result = SCIP_CUTOFF;
15121 else
15122 *result = SCIP_SEPARATED;
15123 }
15124 }
15125
15126 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15127
15128 return SCIP_OKAY;
15129}
15130
15131/** adds symmetry information of constraint to a symmetry detection graph */
15132static
15134 SCIP* scip, /**< SCIP pointer */
15135 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15136 SCIP_CONS* cons, /**< constraint */
15137 SYM_GRAPH* graph, /**< symmetry detection graph */
15138 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15139 )
15140{
15141 SCIP_CONSDATA* consdata;
15142 SCIP_VAR** vars;
15143 SCIP_Real* vals;
15144 SCIP_Real constant = 0.0;
15145 SCIP_Real lhs;
15146 SCIP_Real rhs;
15147 int nlocvars;
15148 int nvars;
15149 int i;
15150
15151 assert(scip != NULL);
15152 assert(cons != NULL);
15153 assert(graph != NULL);
15154 assert(success != NULL);
15155
15156 consdata = SCIPconsGetData(cons);
15157 assert(consdata != NULL);
15158
15159 /* get active variables of the constraint */
15160 nvars = SCIPgetNVars(scip);
15161 nlocvars = consdata->nvars;
15162
15163 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
15164 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
15165
15166 for( i = 0; i < nlocvars; ++i )
15167 {
15168 vars[i] = consdata->vars[i];
15169 vals[i] = consdata->vals[i];
15170 }
15171
15172 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15173 lhs = consdata->lhs - constant;
15174 rhs = consdata->rhs - constant;
15175
15176 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15177 * of the same constraint are rated as equal
15178 */
15179 if ( SCIPisInfinity(scip, rhs) )
15180 {
15181 SCIP_Real tmp;
15182 assert(!SCIPisInfinity(scip, -lhs));
15183
15184 for( i = 0; i < nlocvars; ++i )
15185 vals[i] *= -1;
15186 tmp = rhs;
15187 rhs = -lhs;
15188 lhs = -tmp;
15189 }
15190
15191 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
15192 cons, lhs, rhs, success) );
15193
15194 SCIPfreeBufferArray(scip, &vals);
15195 SCIPfreeBufferArray(scip, &vars);
15196
15197 return SCIP_OKAY;
15198}
15199
15200/*
15201 * Callback methods of constraint handler
15202 */
15203
15204/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15205static
15206SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15207{ /*lint --e{715}*/
15208 assert(scip != NULL);
15209 assert(conshdlr != NULL);
15210 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15211
15212 /* call inclusion method of constraint handler */
15214
15215 *valid = TRUE;
15216
15217 return SCIP_OKAY;
15218}
15219
15220/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15221static
15222SCIP_DECL_CONSFREE(consFreeLinear)
15223{ /*lint --e{715}*/
15224 SCIP_CONSHDLRDATA* conshdlrdata;
15225
15226 assert(scip != NULL);
15227 assert(conshdlr != NULL);
15228 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15229
15230 /* free constraint handler data */
15231 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15232 assert(conshdlrdata != NULL);
15233
15234 conshdlrdataFree(scip, &conshdlrdata);
15235
15236 SCIPconshdlrSetData(conshdlr, NULL);
15237
15238 return SCIP_OKAY;
15239}
15240
15241
15242/** initialization method of constraint handler (called after problem was transformed) */
15243static
15244SCIP_DECL_CONSINIT(consInitLinear)
15245{
15246 SCIP_CONSHDLRDATA* conshdlrdata;
15247 int c;
15248
15249 assert(scip != NULL);
15250
15251 /* check for event handler */
15252 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15253 assert(conshdlrdata != NULL);
15254 assert(conshdlrdata->eventhdlr != NULL);
15255 assert(nconss == 0 || conss != NULL);
15256
15257 conshdlrdata->naddconss = 0;
15258
15259 /* catch events for the constraints */
15260 for( c = 0; c < nconss; ++c )
15261 {
15262 /* catch all events */
15263 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15264 }
15265
15266 return SCIP_OKAY;
15267}
15268
15269
15270/** deinitialization method of constraint handler (called before transformed problem is freed) */
15271static
15272SCIP_DECL_CONSEXIT(consExitLinear)
15273{
15274 SCIP_CONSHDLRDATA* conshdlrdata;
15275 int c;
15276
15277 assert(scip != NULL);
15278
15279 /* check for event handler */
15280 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15281 assert(conshdlrdata != NULL);
15282 assert(conshdlrdata->eventhdlr != NULL);
15283
15284 /* drop events for the constraints */
15285 for( c = nconss - 1; c >= 0; --c )
15286 {
15287 SCIP_CONSDATA* consdata;
15288
15289 consdata = SCIPconsGetData(conss[c]);
15290 assert(consdata != NULL);
15291
15292 if( consdata->eventdata != NULL )
15293 {
15294 /* drop all events */
15295 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15296 assert(consdata->eventdata == NULL);
15297 }
15298 }
15299
15300 return SCIP_OKAY;
15301}
15302
15303/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15304static
15306 SCIP* scip, /**< SCIP data structure */
15307 SCIP_Real lhs, /**< left hand side */
15308 SCIP_Real rhs /**< right hand side */
15309 )
15310{
15311 assert(scip != NULL);
15312
15313 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15314}
15315
15316/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15317static
15319 SCIP* scip, /**< SCIP data structure */
15320 SCIP_Real x /**< value */
15321 )
15322{
15323 assert(scip != NULL);
15324
15325 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15326}
15327
15328/** performs linear constraint type classification as used for MIPLIB
15329 *
15330 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15331 *
15332 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15333 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15334 * Similarly, if specialized constraints were created through the API, these are currently not present.
15335 */
15337 SCIP* scip, /**< SCIP data structure */
15338 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15339 )
15340{
15341 int c;
15342 SCIP_CONSHDLR* conshdlr;
15343 SCIP_CONS** conss;
15344 int nconss;
15345
15346 assert(scip != NULL);
15347 assert(linconsstats != NULL);
15348 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15349 assert(conshdlr != NULL);
15350
15352 {
15353 conss = SCIPgetConss(scip);
15354 nconss = SCIPgetNConss(scip);
15355 }
15356 else
15357 {
15358 conss = SCIPconshdlrGetConss(conshdlr);
15359 nconss = SCIPconshdlrGetNConss(conshdlr);
15360 }
15361
15362 /* reset linear constraint type classification */
15363 SCIPlinConsStatsReset(linconsstats);
15364
15365 /* loop through all constraints */
15366 for( c = 0; c < nconss; c++ )
15367 {
15368 SCIP_CONS* cons;
15369 SCIP_CONSDATA* consdata;
15370 SCIP_Real lhs;
15371 SCIP_Real rhs;
15372 int i;
15373
15374 /* get constraint */
15375 cons = conss[c];
15376 assert(cons != NULL);
15377
15378 /* skip constraints that are not handled by the constraint handler */
15379 if( SCIPconsGetHdlr(cons) != conshdlr )
15380 continue;
15381
15382 /* get constraint data */
15383 consdata = SCIPconsGetData(cons);
15384 assert(consdata != NULL);
15385 rhs = consdata->rhs;
15386 lhs = consdata->lhs;
15387
15388 /* merge multiples and delete variables with zero coefficient */
15389 SCIP_CALL( mergeMultiples(scip, cons) );
15390 for( i = 0; i < consdata->nvars; i++ )
15391 {
15392 assert(!SCIPisZero(scip, consdata->vals[i]));
15393 }
15394
15395 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15396 if( consdata->nvars == 0 )
15397 {
15398 SCIPdebugMsg(scip, "classified as EMPTY: ");
15401
15402 continue;
15403 }
15404
15405 /* is constraint of type SCIP_CONSTYPE_FREE? */
15406 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15407 {
15408 SCIPdebugMsg(scip, "classified as FREE: ");
15411
15412 continue;
15413 }
15414
15415 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15416 if( consdata->nvars == 1 )
15417 {
15418 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15421
15422 continue;
15423 }
15424
15425 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15426 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15427 {
15428 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15431
15432 continue;
15433 }
15434
15435 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15436 if( consdata->nvars == 2 )
15437 {
15438 SCIP_LINCONSTYPE constype;
15439
15440 /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15441 if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15442 && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15443 {
15444 constype = SCIP_LINCONSTYPE_PRECEDENCE;
15445 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15446 }
15447 else
15448 {
15449 constype = SCIP_LINCONSTYPE_VARBOUND;
15450 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15451 }
15453
15454 SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15455
15456 continue;
15457 }
15458
15459 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15460 {
15461 SCIP_Real scale;
15462 SCIP_Real b;
15463 SCIP_Bool unmatched;
15464 int nnegbinvars;
15465
15466 unmatched = FALSE;
15467 nnegbinvars = 0;
15468
15469 scale = REALABS(consdata->vals[0]);
15470
15471 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15472 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15473 {
15474 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15475 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15476 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15477 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15478
15479 if( consdata->vals[i] < 0.0 )
15480 nnegbinvars++;
15481 }
15482
15483 if( !unmatched )
15484 {
15485 if( SCIPisEQ(scip, lhs, rhs) )
15486 {
15487 b = rhs/scale + nnegbinvars;
15488 if( SCIPisEQ(scip, 1.0, b) )
15489 {
15490 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15493
15494 continue;
15495 }
15496 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15497 {
15498 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15501
15502 continue;
15503 }
15504 }
15505
15506 /* compute right hand side divided by scale */
15507 if( !SCIPisInfinity(scip, rhs) )
15508 b = rhs/scale + nnegbinvars;
15509 else
15510 b = SCIPinfinity(scip);
15511
15512 if( SCIPisEQ(scip, 1.0, b) )
15513 {
15514 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15517
15518 /* relax right hand side to prevent further classifications */
15519 rhs = SCIPinfinity(scip);
15520 }
15521 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15522 {
15523 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15525
15527
15528 /* relax right hand side to prevent further classifications */
15529 rhs = SCIPinfinity(scip);
15530 }
15531
15532 if( !SCIPisInfinity(scip, lhs) )
15533 b = lhs/scale + nnegbinvars;
15534 else
15535 b = SCIPinfinity(scip);
15536
15537 if( SCIPisEQ(scip, 1.0, b) )
15538 {
15539 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15542
15543 /* relax left hand side to prevent further classifications */
15544 lhs = -SCIPinfinity(scip);
15545 }
15546
15547 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15548 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15549 continue;
15550 }
15551 }
15552
15553 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15554 /* @todo If coefficients or rhs are not integral, we currently do not check
15555 * if the constraint could be scaled (finitely), such that they are.
15556 */
15557 {
15558 SCIP_Real b;
15559 SCIP_Bool unmatched;
15560
15561 b = rhs;
15562 unmatched = FALSE;
15563 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15564 {
15565 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15566 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15567 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15568 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15569
15570 if( SCIPisNegative(scip, consdata->vals[i]) )
15571 b -= consdata->vals[i];
15572 }
15573 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15574
15575 if( !unmatched )
15576 {
15577 if( SCIPisEQ(scip, lhs, rhs) )
15578 {
15579 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15581
15583
15584 continue;
15585 }
15586 else
15587 {
15588 SCIP_Bool matched;
15589
15590 matched = FALSE;
15591 for( i = 0; i < consdata->nvars && !matched; i++ )
15592 {
15593 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15594 }
15595
15596 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15599 }
15600
15601 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15602 if( SCIPisInfinity(scip, -lhs) )
15603 continue;
15604 else
15605 rhs = SCIPinfinity(scip);
15606 }
15607 }
15608
15609 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15610 {
15611 SCIP_Real b;
15612 SCIP_Bool unmatched;
15613
15614 unmatched = FALSE;
15615
15616 b = rhs;
15617 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15618
15619 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15620 {
15621 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15622 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15623 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15624 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15625 }
15626
15627 if( !unmatched )
15628 {
15629 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15632
15633 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15634 if( SCIPisInfinity(scip, -lhs) )
15635 continue;
15636 else
15637 rhs = SCIPinfinity(scip);
15638 }
15639 }
15640
15641 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15642 {
15643 SCIP_Bool unmatched;
15644
15645 unmatched = FALSE;
15646 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15647 {
15648 if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15649 && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15650 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15651 unmatched = TRUE;
15652 }
15653
15654 if( !unmatched )
15655 {
15656 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15659
15660 continue;
15661 }
15662 }
15663
15664 /* no special structure detected */
15665 SCIPdebugMsg(scip, "classified as GENERAL: ");
15667 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15668 }
15669
15670 return SCIP_OKAY;
15671}
15672
15673
15674/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15675static
15676SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15677{ /*lint --e{715}*/
15678 int c;
15679#ifdef SCIP_STATISTIC
15680 SCIP_CONSHDLRDATA* conshdlrdata;
15681 int ngoodconss;
15682 int nallconss;
15683#endif
15684
15685 /* delete all linear constraints that were upgraded to a more specific constraint type;
15686 * make sure, only active variables remain in the remaining constraints
15687 */
15688 assert(scip != NULL);
15689
15690#ifdef SCIP_STATISTIC
15691 /* count number of well behaved linear constraints */
15692 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15693 assert(conshdlrdata != NULL);
15694
15695 ngoodconss = 0;
15696 nallconss = 0;
15697
15698 for( c = 0; c < nconss; ++c )
15699 {
15700 SCIP_CONSDATA* consdata;
15701
15702 if( SCIPconsIsDeleted(conss[c]) )
15703 continue;
15704
15705 consdata = SCIPconsGetData(conss[c]);
15706 assert(consdata != NULL);
15707
15708 if( consdata->upgraded )
15709 continue;
15710
15711 nallconss++;
15712
15714
15715 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15716 ngoodconss++;
15717 }
15718 if( nallconss )
15719 {
15720 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15721 }
15722#endif
15723
15724 for( c = 0; c < nconss; ++c )
15725 {
15726 SCIP_CONSDATA* consdata;
15727
15728 if( SCIPconsIsDeleted(conss[c]) )
15729 continue;
15730
15731 consdata = SCIPconsGetData(conss[c]);
15732 assert(consdata != NULL);
15733
15734 if( consdata->upgraded )
15735 {
15736 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15737 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15738 */
15739 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15740 }
15741 else
15742 {
15743 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15744 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15745 }
15746 }
15747
15748 return SCIP_OKAY;
15749}
15750
15751/** solving process initialization method of constraint handler */
15752static
15753SCIP_DECL_CONSINITSOL(consInitsolLinear)
15754{ /*lint --e{715}*/
15755 /* add nlrow representation to NLP, if NLP had been constructed */
15757 {
15758 int c;
15759 for( c = 0; c < nconss; ++c )
15760 {
15761 SCIP_CALL( addNlrow(scip, conss[c]) );
15762 }
15763 }
15764
15765 return SCIP_OKAY;
15766}
15767
15768/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15769static
15770SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15771{ /*lint --e{715}*/
15772 int c;
15773
15774 assert(scip != NULL);
15775
15776 /* release the rows and nlrows of all constraints */
15777 for( c = 0; c < nconss; ++c )
15778 {
15779 SCIP_CONSDATA* consdata;
15780
15781 consdata = SCIPconsGetData(conss[c]);
15782 assert(consdata != NULL);
15783
15784 if( consdata->row != NULL )
15785 {
15786 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15787 }
15788
15789 if( consdata->nlrow != NULL )
15790 {
15791 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15792 }
15793 }
15794
15795 /* if this is a restart, convert cutpool rows into linear constraints */
15796 if( restart )
15797 {
15798 int ncutsadded;
15799
15800 ncutsadded = 0;
15801
15802 /* create out of all active cuts in cutpool linear constraints */
15803 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15804
15805 if( ncutsadded > 0 )
15806 {
15808 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15809 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15810 * line correctly
15811 */
15813 }
15814 }
15815
15816 return SCIP_OKAY;
15817}
15818
15819
15820/** constraint activation notification method of constraint handler */
15821static
15822SCIP_DECL_CONSACTIVE(consActiveLinear)
15823{ /*lint --e{715}*/
15824 assert(cons != NULL);
15825
15827 {
15828 SCIP_CALL( addNlrow(scip, cons) );
15829 }
15830
15831 return SCIP_OKAY;
15832}
15833
15834/** constraint deactivation notification method of constraint handler */
15835static
15836SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15837{ /*lint --e{715}*/
15838 SCIP_CONSDATA* consdata;
15839
15840 assert(scip != NULL);
15841 assert(conshdlr != NULL);
15842 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15843 assert(cons != NULL );
15844
15845 /* get constraint data */
15846 consdata = SCIPconsGetData(cons);
15847 assert(consdata != NULL);
15848
15849 if( SCIPconsIsDeleted(cons) )
15850 {
15851 SCIP_CONSHDLRDATA* conshdlrdata;
15852
15853 /* check for event handler */
15854 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15855 assert(conshdlrdata != NULL);
15856 assert(conshdlrdata->eventhdlr != NULL);
15857
15858 /* free event data */
15859 if( consdata->eventdata != NULL )
15860 {
15861 /* drop bound change events of variables */
15862 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15863 }
15864 assert(consdata->eventdata == NULL);
15865 }
15866
15867 /* remove row from NLP, if still in solving
15868 * if we are in exitsolve, the whole NLP will be freed anyway
15869 */
15870 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15871 {
15872 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15873 }
15874
15875 return SCIP_OKAY;
15876}
15877
15878
15879/** frees specific constraint data */
15880static
15881SCIP_DECL_CONSDELETE(consDeleteLinear)
15882{ /*lint --e{715}*/
15883 assert(scip != NULL);
15884 assert(conshdlr != NULL);
15885 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15886
15887 if( (*consdata)->eventdata != NULL )
15888 {
15889 SCIP_CONSHDLRDATA* conshdlrdata;
15890
15891 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15892 assert(conshdlrdata != NULL);
15893
15894 /* drop all events */
15895 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15896 assert((*consdata)->eventdata == NULL);
15897 }
15898
15899 /* free linear constraint */
15900 SCIP_CALL( consdataFree(scip, consdata) );
15901
15902 return SCIP_OKAY;
15903}
15904
15905
15906/** transforms constraint data into data belonging to the transformed problem */
15907static
15908SCIP_DECL_CONSTRANS(consTransLinear)
15909{ /*lint --e{715}*/
15910 SCIP_CONSDATA* sourcedata;
15911 SCIP_CONSDATA* targetdata;
15912
15913 /*debugMsg(scip, "Trans method of linear constraints\n");*/
15914
15915 assert(scip != NULL);
15916 assert(conshdlr != NULL);
15917 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15919 assert(sourcecons != NULL);
15920 assert(targetcons != NULL);
15921
15922 sourcedata = SCIPconsGetData(sourcecons);
15923 assert(sourcedata != NULL);
15924 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15925
15926 /* create linear constraint data for target constraint */
15927 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15928
15929#ifndef NDEBUG
15930 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15931 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15932 {
15933 int n;
15934 for(n = targetdata->nvars - 1; n >= 0; --n )
15935 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15936 }
15937#endif
15938
15939 /* create target constraint */
15940 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15941 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15942 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15943 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15944 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15945
15946 return SCIP_OKAY;
15947}
15948
15949
15950/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15951static
15952SCIP_DECL_CONSINITLP(consInitlpLinear)
15953{ /*lint --e{715}*/
15954 int c;
15955
15956 assert(scip != NULL);
15957 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15958
15959 *infeasible = FALSE;
15960
15961 for( c = 0; c < nconss && !(*infeasible); ++c )
15962 {
15963 assert(SCIPconsIsInitial(conss[c]));
15964 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15965 }
15966
15967 return SCIP_OKAY;
15968}
15969
15970
15971/** separation method of constraint handler for LP solutions */
15972static
15973SCIP_DECL_CONSSEPALP(consSepalpLinear)
15974{ /*lint --e{715}*/
15975 SCIP_CONSHDLRDATA* conshdlrdata;
15976 SCIP_Real loclowerbound;
15977 SCIP_Real glblowerbound;
15978 SCIP_Real cutoffbound;
15979 SCIP_Real maxbound;
15980 SCIP_Bool separatecards;
15981 SCIP_Bool cutoff;
15982 int c;
15983 int depth;
15984 int nrounds;
15985 int maxsepacuts;
15986 int ncuts;
15987
15988 assert(scip != NULL);
15989 assert(conshdlr != NULL);
15990 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15991 assert(result != NULL);
15992
15993 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15994 assert(conshdlrdata != NULL);
15995 depth = SCIPgetDepth(scip);
15996 nrounds = SCIPgetNSepaRounds(scip);
15997
15998 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15999
16000 *result = SCIP_DIDNOTRUN;
16001
16002 /* only call the separator a given number of times at each node */
16003 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16004 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16005 return SCIP_OKAY;
16006
16007 /* get the maximal number of cuts allowed in a separation round */
16008 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16009
16010 /* check if we want to produce knapsack cardinality cuts at this node */
16011 loclowerbound = SCIPgetLocalLowerbound(scip);
16012 glblowerbound = SCIPgetLowerbound(scip);
16013 cutoffbound = SCIPgetCutoffbound(scip);
16014 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16015 separatecards = SCIPisLE(scip, loclowerbound, maxbound);
16016 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
16017
16018 *result = SCIP_DIDNOTFIND;
16019 ncuts = 0;
16020 cutoff = FALSE;
16021
16022 /* check all useful linear constraints for feasibility */
16023 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16024 {
16025 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16026 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16027 }
16028
16029 /* adjust return value */
16030 if( cutoff )
16031 *result = SCIP_CUTOFF;
16032 else if( ncuts > 0 )
16033 *result = SCIP_SEPARATED;
16034
16035 /* combine linear constraints to get more cuts */
16036 /**@todo further cuts of linear constraints */
16037
16038 return SCIP_OKAY;
16039}
16040
16041
16042/** separation method of constraint handler for arbitrary primal solutions */
16043static
16044SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16045{ /*lint --e{715}*/
16046 SCIP_CONSHDLRDATA* conshdlrdata;
16047 int c;
16048 int depth;
16049 int nrounds;
16050 int maxsepacuts;
16051 int ncuts;
16052 SCIP_Bool cutoff;
16053
16054 assert(scip != NULL);
16055 assert(conshdlr != NULL);
16056 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16057 assert(result != NULL);
16058
16059 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16060 assert(conshdlrdata != NULL);
16061 depth = SCIPgetDepth(scip);
16062 nrounds = SCIPgetNSepaRounds(scip);
16063
16064 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16065
16066 *result = SCIP_DIDNOTRUN;
16067
16068 /* only call the separator a given number of times at each node */
16069 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16070 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16071 return SCIP_OKAY;
16072
16073 /* get the maximal number of cuts allowed in a separation round */
16074 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16075
16076 *result = SCIP_DIDNOTFIND;
16077 ncuts = 0;
16078 cutoff = FALSE;
16079
16080 /* check all useful linear constraints for feasibility */
16081 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16082 {
16083 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16084 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16085 }
16086
16087 /* adjust return value */
16088 if( cutoff )
16089 *result = SCIP_CUTOFF;
16090 else if( ncuts > 0 )
16091 *result = SCIP_SEPARATED;
16092
16093 /* combine linear constraints to get more cuts */
16094 /**@todo further cuts of linear constraints */
16095
16096 return SCIP_OKAY;
16097}
16098
16099
16100/** constraint enforcing method of constraint handler for LP solutions */
16101static
16102SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16103{ /*lint --e{715}*/
16104 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16105
16106 return SCIP_OKAY;
16107}
16108
16109/** constraint enforcing method of constraint handler for relaxation solutions */
16110static
16111SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16112{ /*lint --e{715}*/
16113 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16114
16115 return SCIP_OKAY;
16116}
16117
16118/** constraint enforcing method of constraint handler for pseudo solutions */
16119static
16120SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16121{ /*lint --e{715}*/
16122 SCIP_CONSHDLRDATA* conshdlrdata;
16123 SCIP_Bool checkrelmaxabs;
16124 SCIP_Bool violated;
16125 int c;
16126
16127 assert(scip != NULL);
16128 assert(conshdlr != NULL);
16129 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16130 assert(result != NULL);
16131
16132 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16133 assert(conshdlrdata != NULL);
16134
16135 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16136
16137 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16138
16139 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16140 if( objinfeasible )
16141 {
16142 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16143
16144 *result = SCIP_DIDNOTRUN;
16145 return SCIP_OKAY;
16146 }
16147
16148 /* check all linear constraints for feasibility */
16149 violated = FALSE;
16150 for( c = 0; c < nconss && !violated; ++c )
16151 {
16152 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16153 }
16154
16155 if( violated )
16156 *result = SCIP_INFEASIBLE;
16157 else
16158 *result = SCIP_FEASIBLE;
16159
16160 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16161
16162 return SCIP_OKAY;
16163}
16164
16165
16166/** feasibility check method of constraint handler for integral solutions */
16167static
16168SCIP_DECL_CONSCHECK(consCheckLinear)
16169{ /*lint --e{715}*/
16170 SCIP_CONSHDLRDATA* conshdlrdata;
16171 SCIP_Bool checkrelmaxabs;
16172 int c;
16173
16174 assert(scip != NULL);
16175 assert(conshdlr != NULL);
16176 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16177 assert(result != NULL);
16178
16179 *result = SCIP_FEASIBLE;
16180
16181 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16182 assert(conshdlrdata != NULL);
16183
16184 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16185
16186 /*debugMsg(scip, "Check method of linear constraints\n");*/
16187
16188 /* check all linear constraints for feasibility */
16189 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16190 {
16191 SCIP_Bool violated = FALSE;
16192 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16193
16194 if( violated )
16195 {
16196 *result = SCIP_INFEASIBLE;
16197
16198 if( printreason )
16199 {
16200 SCIP_CONSDATA* consdata;
16201 SCIP_Real activity;
16202
16203 consdata = SCIPconsGetData(conss[c]);
16204 assert( consdata != NULL);
16205
16206 activity = consdataGetActivity(scip, consdata, sol);
16207
16208 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16209 SCIPinfoMessage(scip, NULL, ";\n");
16210
16211 if( activity == SCIP_INVALID ) /*lint !e777*/
16212 SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16213 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16214 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16215 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16216 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16217 }
16218 }
16219 }
16220
16221 return SCIP_OKAY;
16222}
16223
16224
16225/** domain propagation method of constraint handler */
16226static
16227SCIP_DECL_CONSPROP(consPropLinear)
16228{ /*lint --e{715}*/
16229 SCIP_CONSHDLRDATA* conshdlrdata;
16230 SCIP_Bool rangedrowpropagation = FALSE;
16231 SCIP_Bool tightenbounds;
16232 SCIP_Bool cutoff;
16233
16234 int nchgbds;
16235 int i;
16236
16237 assert(scip != NULL);
16238 assert(conshdlr != NULL);
16239 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16240 assert(result != NULL);
16241
16242 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16243 assert(conshdlrdata != NULL);
16244
16245 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16246
16247 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16248 if( SCIPinProbing(scip) )
16249 tightenbounds = TRUE;
16250 else
16251 {
16252 int depth;
16253 int propfreq;
16254 int tightenboundsfreq;
16255 int rangedrowfreq;
16256
16257 depth = SCIPgetDepth(scip);
16258 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16259 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16260 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16261 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16262
16263 /* check if we want to do ranged row propagation */
16264 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16265 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16266 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16267 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16268 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16269 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16270 }
16271
16272 cutoff = FALSE;
16273 nchgbds = 0;
16274
16275 /* process constraints marked for propagation */
16276 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16277 {
16279 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16280 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16281 }
16282
16283 /* adjust result code */
16284 if( cutoff )
16285 *result = SCIP_CUTOFF;
16286 else if( nchgbds > 0 )
16287 *result = SCIP_REDUCEDDOM;
16288 else
16289 *result = SCIP_DIDNOTFIND;
16290
16291 return SCIP_OKAY;
16292}
16293
16294
16295#define MAXCONSPRESOLROUNDS 10
16296/** presolving method of constraint handler */
16297static
16298SCIP_DECL_CONSPRESOL(consPresolLinear)
16299{ /*lint --e{715}*/
16300 SCIP_CONSHDLRDATA* conshdlrdata;
16301 SCIP_CONS* cons;
16302 SCIP_CONSDATA* consdata;
16303 SCIP_Real minactivity;
16304 SCIP_Real maxactivity;
16305 SCIP_Bool isminacttight;
16306 SCIP_Bool ismaxacttight;
16307 SCIP_Bool isminsettoinfinity;
16308 SCIP_Bool ismaxsettoinfinity;
16309 SCIP_Bool cutoff;
16310 int oldnfixedvars;
16311 int oldnaggrvars;
16312 int oldnchgbds;
16313 int oldndelconss;
16314 int oldnupgdconss;
16315 int oldnchgcoefs;
16316 int oldnchgsides;
16317 int firstchange;
16318 int firstupgradetry;
16319 int c;
16320
16321 assert(scip != NULL);
16322 assert(conshdlr != NULL);
16323 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16324 assert(result != NULL);
16325
16326 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16327
16328 /* remember old preprocessing counters */
16329 cutoff = FALSE;
16330 oldnfixedvars = *nfixedvars;
16331 oldnaggrvars = *naggrvars;
16332 oldnchgbds = *nchgbds;
16333 oldndelconss = *ndelconss;
16334 oldnupgdconss = *nupgdconss;
16335 oldnchgcoefs = *nchgcoefs;
16336 oldnchgsides = *nchgsides;
16337
16338 /* get constraint handler data */
16339 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16340 assert(conshdlrdata != NULL);
16341
16342 /* process single constraints */
16343 firstchange = INT_MAX;
16344 firstupgradetry = INT_MAX;
16345 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16346 {
16347 int npresolrounds;
16348 SCIP_Bool infeasible;
16349
16350 infeasible = FALSE;
16351
16352 cons = conss[c];
16353 assert(SCIPconsIsActive(cons));
16354 consdata = SCIPconsGetData(cons);
16355 assert(consdata != NULL);
16356
16357 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16358 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16359 {
16360 consdata->lhs = consdata->rhs;
16361 assert(consdata->row == NULL);
16362 }
16363
16364 if( consdata->eventdata == NULL )
16365 {
16366 /* catch bound change events of variables */
16367 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16368 assert(consdata->eventdata != NULL);
16369 }
16370
16371 /* constraint should not be already presolved in the initial round */
16372 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16373 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16374 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16375 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16376
16377 /* incorporate fixings and aggregations in constraint */
16378 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16379
16380 if( infeasible )
16381 {
16382 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16383 cutoff = TRUE;
16384 break;
16385 }
16386
16387 assert(consdata->removedfixings);
16388
16389 /* we can only presolve linear constraints, that are not modifiable */
16390 if( SCIPconsIsModifiable(cons) )
16391 continue;
16392
16393 /* remember the first changed constraint to begin the next aggregation round with */
16394 if( firstchange == INT_MAX && consdata->changed )
16395 firstchange = c;
16396
16397 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16398 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16399 firstupgradetry = c;
16400
16401 /* check, if constraint is already preprocessed */
16402 if( consdata->presolved )
16403 continue;
16404
16405 assert(SCIPconsIsActive(cons));
16406
16407 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16409
16410 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16411 * to avoid nearly infinite cycling due to very small bound changes)
16412 */
16413 npresolrounds = 0;
16414 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16415 {
16416 assert(!cutoff);
16417 npresolrounds++;
16418
16419 /* mark constraint being presolved and propagated */
16420 consdata->presolved = TRUE;
16422
16423 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16424
16425 if( infeasible )
16426 {
16427 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16428 cutoff = TRUE;
16429 break;
16430 }
16431
16432 /* tighten left and right hand side due to integrality */
16433 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16434
16435 if( infeasible )
16436 {
16437 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16438 cutoff = TRUE;
16439 break;
16440 }
16441
16442 /* check bounds */
16443 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16444 {
16445 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16446 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16447 cutoff = TRUE;
16448 break;
16449 }
16450
16451 /* tighten variable's bounds */
16452 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16453 if( cutoff )
16454 break;
16455
16456 /* check for fixed variables */
16457 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16458 if( cutoff )
16459 break;
16460
16461 /* check constraint for infeasibility and redundancy */
16462 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
16463 &isminsettoinfinity, &ismaxsettoinfinity);
16464 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16465 {
16466 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16467 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16468 cutoff = TRUE;
16469 break;
16470 }
16471 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16472 {
16473 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16474 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16475 SCIP_CALL( SCIPdelCons(scip, cons) );
16476 assert(!SCIPconsIsActive(cons));
16477
16478 if( !consdata->upgraded )
16479 (*ndelconss)++;
16480 break;
16481 }
16482 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16483 {
16484 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16485 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16486 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16487 if( !consdata->upgraded )
16488 (*nchgsides)++;
16489 }
16490 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16491 {
16492 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16493 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16495 if( !consdata->upgraded )
16496 (*nchgsides)++;
16497 }
16498
16499 /* handle empty constraint */
16500 if( consdata->nvars == 0 )
16501 {
16502 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16503 {
16504 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16505 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16506 cutoff = TRUE;
16507 }
16508 else
16509 {
16510 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16511 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16512 SCIP_CALL( SCIPdelCons(scip, cons) );
16513 assert(!SCIPconsIsActive(cons));
16514
16515 if( !consdata->upgraded )
16516 (*ndelconss)++;
16517 }
16518 break;
16519 }
16520
16521 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16522 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16523
16524 /* try to simplify inequalities */
16525 if( conshdlrdata->simplifyinequalities )
16526 {
16527 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16528
16529 if( cutoff )
16530 break;
16531 }
16532
16533 /* aggregation variable in equations */
16534 if( conshdlrdata->aggregatevariables )
16535 {
16536 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16537 if( cutoff )
16538 break;
16539 }
16540 }
16541
16542 if( !cutoff && !SCIPisStopped(scip) )
16543 {
16544 /* perform ranged row propagation */
16545 if( conshdlrdata->rangedrowpropagation )
16546 {
16547 int lastnfixedvars;
16548
16549 lastnfixedvars = *nfixedvars;
16550
16551 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16552 if( !cutoff )
16553 {
16554 if( lastnfixedvars < *nfixedvars )
16555 {
16556 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16557 }
16558 }
16559 }
16560
16561 /* extract cliques from constraint */
16562 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16563 {
16564 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16565 nfixedvars, nchgbds, &cutoff) );
16566
16567 /* check if the constraint got redundant or infeasible */
16568 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16569 {
16570 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16571 {
16572 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16573 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16574 cutoff = TRUE;
16575 }
16576 else
16577 {
16578 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16579 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16580 SCIP_CALL( SCIPdelCons(scip, cons) );
16581 assert(!SCIPconsIsActive(cons));
16582
16583 if( !consdata->upgraded )
16584 (*ndelconss)++;
16585 }
16586 }
16587 }
16588
16589 /* convert special equalities */
16590 if( !cutoff && SCIPconsIsActive(cons) )
16591 {
16592 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16593 }
16594
16595 /* apply dual presolving for variables that appear in only one constraint */
16596 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16597 {
16598 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16599 }
16600
16601 /* check if an inequality is parallel to the objective function */
16602 if( !cutoff && SCIPconsIsActive(cons) )
16603 {
16604 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16605 }
16606
16607 /* remember the first changed constraint to begin the next aggregation round with */
16608 if( firstchange == INT_MAX && consdata->changed )
16609 firstchange = c;
16610
16611 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16612 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16613 firstupgradetry = c;
16614 }
16615
16616 /* singleton column stuffing */
16617 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16618 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16619 {
16620 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16621 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16622
16623 /* handle empty constraint */
16624 if( consdata->nvars == 0 )
16625 {
16626 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16627 {
16628 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16629 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16630 cutoff = TRUE;
16631 }
16632 else
16633 {
16634 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16635 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16636 SCIP_CALL( SCIPdelCons(scip, cons) );
16637 assert(!SCIPconsIsActive(cons));
16638
16639 if( !consdata->upgraded )
16640 (*ndelconss)++;
16641 }
16642 break;
16643 }
16644 }
16645 }
16646
16647 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16648 * only apply this expensive procedure in exhaustive presolving timing
16649 */
16650 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16651 {
16652 assert(firstchange >= 0);
16653
16654 if( firstchange < nconss && conshdlrdata->presolusehashing )
16655 {
16656 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16657 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16658 ndelconss, nchgsides) );
16659 }
16660
16661 if( firstchange < nconss && conshdlrdata->presolpairwise )
16662 {
16663 SCIP_CONS** usefulconss;
16664 int nusefulconss;
16665 int firstchangenew;
16666 SCIP_Longint npaircomparisons;
16667
16668 npaircomparisons = 0;
16669 oldndelconss = *ndelconss;
16670 oldnchgsides = *nchgsides;
16671 oldnchgcoefs = *nchgcoefs;
16672
16673 /* allocate temporary memory */
16674 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16675
16676 nusefulconss = 0;
16677 firstchangenew = -1;
16678 for( c = 0; c < nconss; ++c )
16679 {
16680 /* update firstchange */
16681 if( c == firstchange )
16682 firstchangenew = nusefulconss;
16683
16684 /* ignore inactive and modifiable constraints */
16685 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16686 continue;
16687
16688 usefulconss[nusefulconss] = conss[c];
16689 ++nusefulconss;
16690 }
16691 firstchange = firstchangenew;
16692 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16693
16694 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16695 {
16696 /* constraint has become inactive or modifiable during pairwise presolving */
16697 if( usefulconss[c] == NULL )
16698 continue;
16699
16700 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16701
16702 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16703 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16704 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16705
16706 if( npaircomparisons > conshdlrdata->nmincomparisons )
16707 {
16708 assert(npaircomparisons > 0);
16709 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16710 break;
16711 oldndelconss = *ndelconss;
16712 oldnchgsides = *nchgsides;
16713 oldnchgcoefs = *nchgcoefs;
16714 npaircomparisons = 0;
16715 }
16716 }
16717 /* free temporary memory */
16718 SCIPfreeBufferArray(scip, &usefulconss);
16719 }
16720 }
16721
16722 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16723 * in linear constraints and we therefore have full information about it
16724 */
16725 if( !cutoff && firstupgradetry < nconss
16726 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16727 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16728 )
16729 {
16730 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16731 {
16732 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds, nchgvartypes) );
16733 }
16734 }
16735
16736 /* try to upgrade constraints into a more specific constraint type;
16737 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16738 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16739 */
16740 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16741 {
16742 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16743 {
16744 cons = conss[c];
16745
16746 /* don't upgrade modifiable constraints */
16747 if( SCIPconsIsModifiable(cons) )
16748 continue;
16749
16750 consdata = SCIPconsGetData(cons);
16751 assert(consdata != NULL);
16752
16753 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16754 if( consdata->upgradetried )
16755 continue;
16756 /* @todo force that upgrade will be performed later? */
16757 if( !consdata->presolved )
16758 continue;
16759
16760 consdata->upgradetried = TRUE;
16761 if( SCIPconsIsActive(cons) )
16762 {
16763 SCIP_CONS* upgdcons;
16764
16765 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16766 if( upgdcons != NULL )
16767 {
16768 /* add the upgraded constraint to the problem */
16769 SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16770 SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16771 (*nupgdconss)++;
16772
16773 /* mark the linear constraint being upgraded and to be removed after presolving;
16774 * don't delete it directly, because it may help to preprocess other linear constraints
16775 */
16776 assert(!consdata->upgraded);
16777 consdata->upgraded = TRUE;
16778
16779 /* delete upgraded inequalities immediately;
16780 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16781 */
16782 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16783 || !conshdlrdata->presolpairwise
16784 || (conshdlrdata->maxaggrnormscale == 0.0) )
16785 {
16786 SCIP_CALL( SCIPdelCons(scip, cons) );
16787 }
16788 }
16789 }
16790 }
16791 }
16792
16793 /* return the correct result code */
16794 if( cutoff )
16795 *result = SCIP_CUTOFF;
16796 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16797 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16798 *result = SCIP_SUCCESS;
16799 else
16800 *result = SCIP_DIDNOTFIND;
16801
16802 return SCIP_OKAY;
16803}
16804
16805
16806/** propagation conflict resolving method of constraint handler */
16807static
16808SCIP_DECL_CONSRESPROP(consRespropLinear)
16809{ /*lint --e{715}*/
16810 assert(scip != NULL);
16811 assert(cons != NULL);
16812 assert(result != NULL);
16813
16814 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16815
16816 return SCIP_OKAY;
16817}
16818
16819
16820/** variable rounding lock method of constraint handler */
16821static
16822SCIP_DECL_CONSLOCK(consLockLinear)
16823{ /*lint --e{715}*/
16824 SCIP_CONSDATA* consdata;
16825 SCIP_Bool haslhs;
16826 SCIP_Bool hasrhs;
16827 int i;
16828
16829 assert(scip != NULL);
16830 assert(cons != NULL);
16831 consdata = SCIPconsGetData(cons);
16832 assert(consdata != NULL);
16833
16834 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16835 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16836
16837 /* update rounding locks of every single variable */
16838 for( i = 0; i < consdata->nvars; ++i )
16839 {
16840 if( SCIPisPositive(scip, consdata->vals[i]) )
16841 {
16842 if( haslhs )
16843 {
16844 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16845 }
16846 if( hasrhs )
16847 {
16848 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16849 }
16850 }
16851 else
16852 {
16853 if( haslhs )
16854 {
16855 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16856 }
16857 if( hasrhs )
16858 {
16859 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16860 }
16861 }
16862 }
16863
16864 return SCIP_OKAY;
16865}
16866
16867
16868/** variable deletion method of constraint handler */
16869static
16870SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16871{
16872 assert(scip != NULL);
16873 assert(conshdlr != NULL);
16874 assert(conss != NULL || nconss == 0);
16875
16876 if( nconss > 0 )
16877 {
16878 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16879 }
16880
16881 return SCIP_OKAY;
16882}
16883
16884/** constraint display method of constraint handler */
16885static
16886SCIP_DECL_CONSPRINT(consPrintLinear)
16887{ /*lint --e{715}*/
16888 assert(scip != NULL);
16889 assert(conshdlr != NULL);
16890 assert(cons != NULL);
16891
16893
16894 return SCIP_OKAY;
16895}
16896
16897/** constraint copying method of constraint handler */
16898static
16899SCIP_DECL_CONSCOPY(consCopyLinear)
16900{ /*lint --e{715}*/
16901 SCIP_VAR** sourcevars;
16902 SCIP_Real* sourcecoefs;
16903 const char* consname;
16904 int nvars;
16905
16906 assert(scip != NULL);
16907 assert(sourcescip != NULL);
16908 assert(sourcecons != NULL);
16909
16910 /* get variables and coefficients of the source constraint */
16911 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16912 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16913 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16914
16915 if( name != NULL )
16916 consname = name;
16917 else
16918 consname = SCIPconsGetName(sourcecons);
16919
16920 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16921 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16922 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16923 assert(cons != NULL || *valid == FALSE);
16924
16925 /* @todo should also the checkabsolute flag of the constraint be copied? */
16926
16927 return SCIP_OKAY;
16928}
16929
16930/** find operators '<=', '==', '>=', [free] in input string and return those places
16931 *
16932 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16933 */
16934static
16936 const char* str, /**< null terminated input string */
16937 char** firstoperator, /**< pointer to store the string starting at the first operator */
16938 char** secondoperator, /**< pointer to store the string starting at the second operator */
16939 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16940 )
16941{
16942 char* curr;
16943
16944 assert(str != NULL);
16945 assert(firstoperator != NULL);
16946 assert(secondoperator != NULL);
16947
16948 *firstoperator = NULL;
16949 *secondoperator = NULL;
16950
16951 curr = (char*)str;
16952 *success = TRUE;
16953
16954 /* loop over the input string to find all operators */
16955 while( *curr && *success )
16956 {
16957 SCIP_Bool found = FALSE;
16958 int increment = 1;
16959
16960 /* try if we found a possible operator */
16961 switch( *curr )
16962 {
16963 case '<':
16964 case '=':
16965 case '>':
16966
16967 /* check if the two characters curr[0,1] form an operator together */
16968 if( curr[1] == '=' )
16969 {
16970 found = TRUE;
16971
16972 /* update increment to continue after this operator */
16973 increment = 2;
16974 }
16975 break;
16976 case '[':
16977 if( strncmp(curr, "[free]", 6) == 0 )
16978 {
16979 found = TRUE;
16980
16981 /* update increment to continue after this operator */
16982 increment = 6;
16983 }
16984 break;
16985 default:
16986 break;
16987 }
16988
16989 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16990 if( found )
16991 {
16992 if( *firstoperator == NULL )
16993 {
16994 *firstoperator = curr;
16995 }
16996 else
16997 {
16998 if( *secondoperator != NULL )
16999 {
17000 SCIPerrorMessage("Found more than two operators in line %s\n", str);
17001 *success = FALSE;
17002 }
17003 else if( strncmp(*firstoperator, "<=", 2) != 0 )
17004 {
17005 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17006 *success = FALSE;
17007 }
17008 else if( strncmp(curr, "<=", 2) != 0 )
17009 {
17010 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17011 *success = FALSE;
17012 }
17013
17014 *secondoperator = curr;
17015 }
17016 }
17017
17018 curr += increment;
17019 }
17020
17021 /* check if we did find at least one operator */
17022 if( *success )
17023 {
17024 if( *firstoperator == NULL )
17025 {
17026 SCIPerrorMessage("Could not find any operator in line %s\n", str);
17027 *success = FALSE;
17028 }
17029 }
17030}
17031
17032/** constraint parsing method of constraint handler */
17033static
17034SCIP_DECL_CONSPARSE(consParseLinear)
17035{ /*lint --e{715}*/
17036 SCIP_VAR** vars;
17037 SCIP_Real* coefs;
17038 int nvars;
17039 int coefssize;
17040 int requsize;
17041 SCIP_Real lhs;
17042 SCIP_Real rhs;
17043 char* endptr;
17044 char* firstop;
17045 char* secondop;
17046 SCIP_Bool operatorsuccess;
17047 char* lhsstrptr;
17048 char* rhsstrptr;
17049 char* varstrptr;
17050
17051 assert(scip != NULL);
17052 assert(success != NULL);
17053 assert(str != NULL);
17054 assert(name != NULL);
17055 assert(cons != NULL);
17056
17057 /* set left and right hand side to their default values */
17058 lhs = -SCIPinfinity(scip);
17059 rhs = SCIPinfinity(scip);
17060
17061 (*success) = FALSE;
17062
17063 /* return of string empty */
17064 if( !*str )
17065 return SCIP_OKAY;
17066
17067 /* ignore whitespace */
17068 SCIP_CALL( SCIPskipSpace((char**)&str) );
17069
17070 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17071 * and the special word [free]
17072 */
17073 findOperators(str, &firstop, &secondop, &operatorsuccess);
17074
17075 /* if the grammar is not valid for parsing a linear constraint, return */
17076 if( ! operatorsuccess )
17077 return SCIP_OKAY;
17078
17079 varstrptr = (char *)str;
17080 lhsstrptr = rhsstrptr = NULL;
17081 assert(firstop != NULL);
17082
17083 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17084 switch( *firstop )
17085 {
17086 case '<':
17087 assert(firstop[1] == '=');
17088 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17089 if( secondop != NULL )
17090 {
17091 assert(secondop[0] == '<' && secondop[1] == '=');
17092 lhsstrptr = (char *)str;
17093 varstrptr = firstop + 2;
17094 rhsstrptr = secondop + 2;
17095 }
17096 else
17097 {
17098 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17099 lhsstrptr = NULL;
17100 varstrptr = (char *)str;
17101 rhsstrptr = firstop + 2;
17102 }
17103 break;
17104 case '>':
17105 assert(firstop[1] == '=');
17106 assert(secondop == NULL);
17107 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17108 lhsstrptr = firstop + 2;
17109 break;
17110 case '=':
17111 assert(firstop[1] == '=');
17112 assert(secondop == NULL);
17113 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17114 rhsstrptr = firstop + 2;
17115 lhsstrptr = firstop + 2;
17116 break;
17117 case '[':
17118 assert(strncmp(firstop, "[free]", 6) == 0);
17119 assert(secondop == NULL);
17120 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17121 break;
17122 default:
17123 /* it should not be possible that a different character appears in that position */
17124 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17125 return SCIP_READERROR;
17126 }
17127
17128 /* parse left hand side, if necessary */
17129 if( lhsstrptr != NULL )
17130 {
17131 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17132 {
17133 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17134 return SCIP_OKAY;
17135 }
17136
17137 /* in case of an equation, assign the left also to the right hand side */
17138 if( rhsstrptr == lhsstrptr )
17139 rhs = lhs;
17140 }
17141
17142 /* parse right hand side, if different from left hand side */
17143 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17144 {
17145 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17146 {
17147 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17148 return SCIP_OKAY;
17149 }
17150 }
17151
17152 /* initialize buffers for storing the variables and coefficients */
17153 coefssize = 100;
17154 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17155 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17156
17157 assert(varstrptr != NULL);
17158
17159 /* parse linear sum to get variables and coefficients */
17160 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17161
17162 if( *success && requsize > coefssize )
17163 {
17164 /* realloc buffers and try again */
17165 coefssize = requsize;
17166 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17167 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17168
17169 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17170 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17171 }
17172
17173 if( !*success )
17174 {
17175 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17176 }
17177 else
17178 {
17179 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17180 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17181 }
17182
17183 SCIPfreeBufferArray(scip, &coefs);
17184 SCIPfreeBufferArray(scip, &vars);
17185
17186 return SCIP_OKAY;
17187}
17188
17189
17190/** constraint method of constraint handler which returns the variables (if possible) */
17191static
17192SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17193{ /*lint --e{715}*/
17194 SCIP_CONSDATA* consdata;
17195
17196 consdata = SCIPconsGetData(cons);
17197 assert(consdata != NULL);
17198
17199 if( varssize < consdata->nvars )
17200 (*success) = FALSE;
17201 else
17202 {
17203 assert(vars != NULL);
17204
17205 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17206 (*success) = TRUE;
17207 }
17208
17209 return SCIP_OKAY;
17210}
17211
17212/**! [Callback for the number of variables]*/
17213/** constraint method of constraint handler which returns the number of variables (if possible) */
17214static
17215SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17216{ /*lint --e{715}*/
17217 SCIP_CONSDATA* consdata;
17218
17219 consdata = SCIPconsGetData(cons);
17220 assert(consdata != NULL);
17221
17222 (*nvars) = consdata->nvars;
17223 (*success) = TRUE;
17224
17225 return SCIP_OKAY;
17226}
17227/**! [Callback for the number of variables]*/
17228
17229/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17230static
17231SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17232{ /*lint --e{715}*/
17233 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17234
17235 return SCIP_OKAY;
17236}
17237
17238/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17239static
17240SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17241{ /*lint --e{715}*/
17242 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17243
17244 return SCIP_OKAY;
17245}
17246
17247/*
17248 * Callback methods of event handler
17249 */
17250
17251/** execution method of event handler */
17252static
17253SCIP_DECL_EVENTEXEC(eventExecLinear)
17254{ /*lint --e{715}*/
17255 SCIP_CONS* cons;
17256 SCIP_CONSDATA* consdata;
17257 SCIP_VAR* var;
17258 SCIP_EVENTTYPE eventtype;
17259
17260 assert(scip != NULL);
17261 assert(eventhdlr != NULL);
17262 assert(eventdata != NULL);
17263 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17264 assert(event != NULL);
17265
17266 cons = eventdata->cons;
17267 assert(cons != NULL);
17268 consdata = SCIPconsGetData(cons);
17269 assert(consdata != NULL);
17270
17271 /* we can skip events droped for deleted constraints */
17272 if( SCIPconsIsDeleted(cons) )
17273 return SCIP_OKAY;
17274
17275 eventtype = SCIPeventGetType(event);
17276 var = SCIPeventGetVar(event);
17277
17278 if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17279 {
17280 SCIP_Real oldbound;
17281 SCIP_Real newbound;
17282 SCIP_Real val;
17283 int varpos;
17284
17285 varpos = eventdata->varpos;
17286 assert(0 <= varpos && varpos < consdata->nvars);
17287 oldbound = SCIPeventGetOldbound(event);
17288 newbound = SCIPeventGetNewbound(event);
17289 assert(var != NULL);
17290 assert(consdata->vars[varpos] == var);
17291 val = consdata->vals[varpos];
17292
17293 /* we only need to update the activities if the constraint is active,
17294 * otherwise we mark them to be invalid
17295 */
17296 if( SCIPconsIsActive(cons) )
17297 {
17298 /* update the activity values */
17299 if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17300 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17301 else
17302 {
17303 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17304 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17305 }
17306 }
17307 else
17309
17310 consdata->presolved = FALSE;
17311 consdata->rangedrowpropagated = 0;
17312
17313 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17314 if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17315 {
17317
17318 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17319 if( consdata->maxactdeltavar == var )
17320 {
17321 consdata->maxactdelta = SCIP_INVALID;
17322 consdata->maxactdeltavar = NULL;
17323 }
17324
17325 /* check whether bound tightening might now be successful */
17326 if( consdata->boundstightened > 0)
17327 {
17328 switch( eventtype )
17329 {
17331 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17332 consdata->boundstightened = 0;
17333 break;
17335 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17336 consdata->boundstightened = 0;
17337 break;
17338 default:
17339 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17340 return SCIP_INVALIDDATA;
17341 }
17342 }
17343 }
17344 /* update maximal activity delta if a bound was relaxed */
17345 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17346 {
17347 SCIP_Real lb;
17348 SCIP_Real ub;
17349 SCIP_Real domain;
17350 SCIP_Real delta;
17351
17352 assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17353
17354 lb = SCIPvarGetLbLocal(var);
17355 ub = SCIPvarGetUbLocal(var);
17356
17357 domain = ub - lb;
17358 delta = REALABS(val) * domain;
17359
17360 if( delta > consdata->maxactdelta )
17361 {
17362 consdata->maxactdelta = delta;
17363 consdata->maxactdeltavar = var;
17364 }
17365 }
17366 }
17367 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17368 {
17369 /* we want to remove the fixed variable */
17370 consdata->presolved = FALSE;
17371 consdata->removedfixings = FALSE;
17372 consdata->rangedrowpropagated = 0;
17373
17374 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17375 if( consdata->maxactdeltavar == var )
17376 {
17377 consdata->maxactdelta = SCIP_INVALID;
17378 consdata->maxactdeltavar = NULL;
17379 }
17380 }
17381 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17382 {
17383 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17386 consdata->presolved = FALSE;
17387 }
17388 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17389 {
17390 SCIP_Real oldbound;
17391 SCIP_Real newbound;
17392 SCIP_Real val;
17393 int varpos;
17394
17395 varpos = eventdata->varpos;
17396 assert(0 <= varpos && varpos < consdata->nvars);
17397 oldbound = SCIPeventGetOldbound(event);
17398 newbound = SCIPeventGetNewbound(event);
17399 assert(var != NULL);
17400 assert(consdata->vars[varpos] == var);
17401 val = consdata->vals[varpos];
17402
17403 consdata->rangedrowpropagated = 0;
17404
17405 /* update the activity values */
17406 if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17407 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17408 else
17409 {
17410 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17411 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17412 }
17413
17414 /* if the variable is binary but not fixed it had to become binary due to this global change */
17416 {
17418 consdata->indexsorted = FALSE;
17419 else
17420 consdata->coefsorted = FALSE;
17421 }
17422 }
17423 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17424 {
17426
17427 /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17428 consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17429
17430 /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17431 consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17432 }
17433 else
17434 {
17435 assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17436 consdata->varsdeleted = TRUE;
17437 }
17438
17439 return SCIP_OKAY;
17440}
17441
17442
17443/*
17444 * Callback methods of conflict handler
17445 */
17446
17447/** conflict processing method of conflict handler (called when conflict was found) */
17448static
17449SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17450{ /*lint --e{715}*/
17451 SCIP_VAR** vars;
17452 SCIP_Real* vals;
17453 SCIP_Real lhs;
17454 int i;
17455
17456 assert(scip != NULL);
17457 assert(conflicthdlr != NULL);
17458 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17459 assert(bdchginfos != NULL || nbdchginfos == 0);
17460 assert(result != NULL);
17461
17462 /* don't process already resolved conflicts */
17463 if( resolved )
17464 {
17465 *result = SCIP_DIDNOTRUN;
17466 return SCIP_OKAY;
17467 }
17468
17469 *result = SCIP_DIDNOTFIND;
17470
17471 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17472 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17473 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17474 lhs = 1.0;
17475 for( i = 0; i < nbdchginfos; ++i )
17476 {
17477 assert(bdchginfos != NULL);
17478
17479 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17480
17481 /* we can only treat binary variables */
17482 /**@todo extend linear conflict constraints to some non-binary cases */
17483 if( !SCIPvarIsBinary(vars[i]) )
17484 break;
17485
17486 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17487 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17488 vals[i] = 1.0;
17489 else
17490 {
17491 vals[i] = -1.0;
17492 lhs -= 1.0;
17493 }
17494 }
17495
17496 if( i == nbdchginfos )
17497 {
17498 SCIP_CONS* cons;
17499 SCIP_CONS* upgdcons;
17500 char consname[SCIP_MAXSTRLEN];
17501
17502 /* create a constraint out of the conflict set */
17504 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17505 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17506
17507 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17508 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17509 if( upgdcons != NULL )
17510 {
17511 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17512 cons = upgdcons;
17513 }
17514
17515 /* add conflict to SCIP */
17516 SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17517
17518 *result = SCIP_CONSADDED;
17519 }
17520
17521 /* free temporary memory */
17522 SCIPfreeBufferArray(scip, &vals);
17523 SCIPfreeBufferArray(scip, &vars);
17524
17525 return SCIP_OKAY;
17526}
17527
17528
17529/*
17530 * Nonlinear constraint upgrading
17531 */
17532
17533/** tries to upgrade a nonlinear constraint into a linear constraint */
17534static
17535SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17536{
17537 SCIP_CONSDATA* consdata;
17538 SCIP_EXPR* expr;
17539 SCIP_Real lhs;
17540 SCIP_Real rhs;
17541 int i;
17542
17543 assert(nupgdconss != NULL);
17544 assert(upgdconss != NULL);
17545 assert(upgdconsssize > 0);
17546
17547 expr = SCIPgetExprNonlinear(cons);
17548 assert(expr != NULL);
17549
17550 /* not a linear constraint if the expression is not a sum
17551 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17552 */
17553 if( !SCIPisExprSum(scip, expr) )
17554 return SCIP_OKAY;
17555
17556 /* if at least one child is not a variable, then not a linear constraint */
17557 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17558 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17559 return SCIP_OKAY;
17560
17561 /* consider constant part of the sum expression */
17564
17565 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17566 0, NULL, NULL, lhs, rhs,
17570 SCIPconsIsStickingAtNode(cons)) );
17571 assert(upgdconss[0] != NULL);
17572
17573 consdata = SCIPconsGetData(upgdconss[0]);
17574
17575 /* add linear terms */
17577 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17578 {
17580 }
17581
17582 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17583 consdata->checkabsolute = TRUE;
17584
17585 *nupgdconss = 1;
17586
17587 SCIPdebugMsg(scip, "created linear constraint:\n");
17588 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17589
17590 return SCIP_OKAY;
17591} /*lint !e715*/
17592
17593/*
17594 * constraint specific interface methods
17595 */
17596
17597/** creates the handler for linear constraints and includes it in SCIP */
17599 SCIP* scip /**< SCIP data structure */
17600 )
17601{
17602 SCIP_CONSHDLRDATA* conshdlrdata;
17603 SCIP_CONSHDLR* conshdlr;
17604 SCIP_EVENTHDLR* eventhdlr;
17605 SCIP_CONFLICTHDLR* conflicthdlr;
17606
17607 assert(scip != NULL);
17608
17609 /* create event handler for bound change events */
17611 eventExecLinear, NULL) );
17612
17613 /* create conflict handler for linear constraints */
17615 conflictExecLinear, NULL) );
17616
17617 /* create constraint handler data */
17618 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17619
17620 /* include constraint handler */
17623 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17624 conshdlrdata) );
17625
17626 assert(conshdlr != NULL);
17627
17628 /* set non-fundamental callbacks via specific setter functions */
17629 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17630 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17631 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17632 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17633 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17634 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17635 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17636 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17637 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17638 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17639 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17640 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17641 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17642 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17643 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17645 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17648 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17649 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17651 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17652 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17653 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17654 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17655
17656 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17657 {
17658 /* include the linear constraint upgrade in the nonlinear constraint handler */
17660 }
17661
17662 /* add linear constraint handler parameters */
17664 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17665 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17666 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17668 "constraints/" CONSHDLR_NAME "/maxrounds",
17669 "maximal number of separation rounds per node (-1: unlimited)",
17670 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17672 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17673 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17674 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17676 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17677 "maximal number of cuts separated per separation round",
17678 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17680 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17681 "maximal number of cuts separated per separation round in the root node",
17682 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17684 "constraints/" CONSHDLR_NAME "/presolpairwise",
17685 "should pairwise constraint comparison be performed in presolving?",
17686 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17688 "constraints/" CONSHDLR_NAME "/presolusehashing",
17689 "should hash table be used for detecting redundant constraints in advance",
17690 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17692 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17693 "number for minimal pairwise presolve comparisons",
17694 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17696 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17697 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17698 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17700 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17701 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17702 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17704 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17705 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17706 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17708 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17709 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17710 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17712 "constraints/" CONSHDLR_NAME "/separateall",
17713 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17714 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17716 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17717 "should presolving search for aggregations in equations",
17718 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17720 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17721 "should presolving try to simplify inequalities",
17722 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17724 "constraints/" CONSHDLR_NAME "/dualpresolving",
17725 "should dual presolving steps be performed?",
17726 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17728 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17729 "should stuffing of singleton continuous variables be performed?",
17730 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17732 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17733 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17734 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17736 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17737 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17739 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17740 "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)?",
17741 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17743 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17744 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17745 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17747 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17748 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17749 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17751 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17752 "should presolving try to detect subsets of constraints parallel to the objective function?",
17753 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17755 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17756 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17757 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17759 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17760 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17761 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17763 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17764 "maximum depth to apply ranged row propagation",
17765 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17767 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17768 "frequency for applying ranged row propagation",
17769 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17771 "constraints/" CONSHDLR_NAME "/multaggrremove",
17772 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17773 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17775 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17776 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17777 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17779 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17780 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17781 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17783 "constraints/" CONSHDLR_NAME "/extractcliques",
17784 "should Cliques be extracted?",
17785 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17786
17787 return SCIP_OKAY;
17788}
17789
17790/** includes a linear constraint update method into the linear constraint handler */
17792 SCIP* scip, /**< SCIP data structure */
17793 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17794 int priority, /**< priority of upgrading method */
17795 const char* conshdlrname /**< name of the constraint handler */
17796 )
17797{
17798 SCIP_CONSHDLR* conshdlr;
17799 SCIP_CONSHDLRDATA* conshdlrdata;
17800 SCIP_LINCONSUPGRADE* linconsupgrade;
17802 char paramdesc[SCIP_MAXSTRLEN];
17803
17804 assert(scip != NULL);
17805 assert(linconsupgd != NULL);
17806 assert(conshdlrname != NULL );
17807
17808 /* find the linear constraint handler */
17809 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17810 if( conshdlr == NULL )
17811 {
17812 SCIPerrorMessage("linear constraint handler not found\n");
17813 return SCIP_PLUGINNOTFOUND;
17814 }
17815
17816 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17817 assert(conshdlrdata != NULL);
17818
17819 /* check if linear constraint update method already exists in constraint handler data */
17820 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17821 {
17822 /* create a linear constraint upgrade data object */
17823 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17824
17825 /* insert linear constraint update method into constraint handler data */
17826 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17827
17828 /* adds parameter to turn on and off the upgrading step */
17829 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17830 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17832 paramname, paramdesc,
17833 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17834 }
17835
17836 return SCIP_OKAY;
17837}
17838
17839/** creates and captures a linear constraint
17840 *
17841 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17842 */
17844 SCIP* scip, /**< SCIP data structure */
17845 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17846 const char* name, /**< name of constraint */
17847 int nvars, /**< number of nonzeros in the constraint */
17848 SCIP_VAR** vars, /**< array with variables of constraint entries */
17849 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17850 SCIP_Real lhs, /**< left hand side of constraint */
17851 SCIP_Real rhs, /**< right hand side of constraint */
17852 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17853 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17854 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17855 * Usually set to TRUE. */
17856 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17857 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17858 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17859 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17860 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17861 * Usually set to TRUE. */
17862 SCIP_Bool local, /**< is constraint only valid locally?
17863 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17864 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17865 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17866 * adds coefficients to this constraint. */
17867 SCIP_Bool dynamic, /**< is constraint subject to aging?
17868 * Usually set to FALSE. Set to TRUE for own cuts which
17869 * are separated as constraints. */
17870 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17871 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17872 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17873 * if it may be moved to a more global node?
17874 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17875 )
17876{
17877 SCIP_CONSHDLR* conshdlr;
17878 SCIP_CONSDATA* consdata;
17879 int j;
17880
17881 assert(scip != NULL);
17882 assert(cons != NULL);
17883
17884 /* find the linear constraint handler */
17885 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17886 if( conshdlr == NULL )
17887 {
17888 SCIPerrorMessage("linear constraint handler not found\n");
17889 return SCIP_PLUGINNOTFOUND;
17890 }
17891
17892 for( j = 0; j < nvars; ++j )
17893 {
17894 if( SCIPisInfinity(scip, REALABS(vals[j])) )
17895 {
17896 SCIPerrorMessage("coefficient of variable <%s> is infinite.\n", SCIPvarGetName(vars[j]));
17897 SCIPABORT();
17898 return SCIP_INVALIDDATA;
17899 }
17900 }
17901
17902 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17903 * constraint after presolving we have to ensure that it holds active variables
17904 */
17905 if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17906 {
17907 SCIP_VAR** consvars;
17908 SCIP_Real* consvals;
17909 SCIP_Real constant = 0.0;
17910 int nconsvars;
17911 int requiredsize;
17912
17913 nconsvars = nvars;
17914 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17915 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17916
17917 /* get active variables for new constraint */
17918 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17919
17920 /* if space was not enough we need to resize the buffers */
17921 if( requiredsize > nconsvars )
17922 {
17923 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17924 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17925
17926 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17927 assert(requiredsize <= nconsvars);
17928 }
17929
17930 /* adjust sides and check that we do not subtract infinity values */
17931 if( SCIPisInfinity(scip, REALABS(constant)) )
17932 {
17933 if( constant < 0.0 )
17934 {
17935 if( SCIPisInfinity(scip, lhs) )
17936 {
17937 SCIPfreeBufferArray(scip, &consvals);
17938 SCIPfreeBufferArray(scip, &consvars);
17939
17940 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);
17941
17942 SCIPABORT();
17943 return SCIP_INVALIDDATA; /*lint !e527*/
17944 }
17945 if( SCIPisInfinity(scip, rhs) )
17946 {
17947 SCIPfreeBufferArray(scip, &consvals);
17948 SCIPfreeBufferArray(scip, &consvars);
17949
17950 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);
17951
17952 SCIPABORT();
17953 return SCIP_INVALIDDATA; /*lint !e527*/
17954 }
17955
17956 lhs = -SCIPinfinity(scip);
17957 rhs = -SCIPinfinity(scip);
17958 }
17959 else
17960 {
17961 if( SCIPisInfinity(scip, -lhs) )
17962 {
17963 SCIPfreeBufferArray(scip, &consvals);
17964 SCIPfreeBufferArray(scip, &consvars);
17965
17966 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);
17967
17968 SCIPABORT();
17969 return SCIP_INVALIDDATA; /*lint !e527*/
17970 }
17971 if( SCIPisInfinity(scip, -rhs) )
17972 {
17973 SCIPfreeBufferArray(scip, &consvals);
17974 SCIPfreeBufferArray(scip, &consvars);
17975
17976 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);
17977
17978 SCIPABORT();
17979 return SCIP_INVALIDDATA; /*lint !e527*/
17980 }
17981
17982 lhs = SCIPinfinity(scip);
17983 rhs = SCIPinfinity(scip);
17984 }
17985 }
17986 else
17987 {
17988 if( !SCIPisInfinity(scip, REALABS(lhs)) )
17989 lhs -= constant;
17990 if( !SCIPisInfinity(scip, REALABS(rhs)) )
17991 rhs -= constant;
17992
17993 if( SCIPisInfinity(scip, -lhs) )
17994 lhs = -SCIPinfinity(scip);
17995 else if( SCIPisInfinity(scip, lhs) )
17996 lhs = SCIPinfinity(scip);
17997
17998 if( SCIPisInfinity(scip, rhs) )
17999 rhs = SCIPinfinity(scip);
18000 else if( SCIPisInfinity(scip, -rhs) )
18001 rhs = -SCIPinfinity(scip);
18002 }
18003
18004 /* create constraint data */
18005 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
18006 assert(consdata != NULL);
18007
18008 SCIPfreeBufferArray(scip, &consvals);
18009 SCIPfreeBufferArray(scip, &consvars);
18010 }
18011 else
18012 {
18013 /* create constraint data */
18014 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18015 assert(consdata != NULL);
18016 }
18017
18018#ifndef NDEBUG
18019 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18020 if( check || enforce )
18021 {
18022 int n;
18023 for(n = consdata->nvars - 1; n >= 0; --n )
18024 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18025 }
18026#endif
18027
18028 /* create constraint */
18029 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18030 local, modifiable, dynamic, removable, stickingatnode) );
18031
18032 return SCIP_OKAY;
18033}
18034
18035/** creates and captures a linear constraint
18036 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18037 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18038 *
18039 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18040 *
18041 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18042 */
18044 SCIP* scip, /**< SCIP data structure */
18045 SCIP_CONS** cons, /**< pointer to hold the created constraint */
18046 const char* name, /**< name of constraint */
18047 int nvars, /**< number of nonzeros in the constraint */
18048 SCIP_VAR** vars, /**< array with variables of constraint entries */
18049 SCIP_Real* vals, /**< array with coefficients of constraint entries */
18050 SCIP_Real lhs, /**< left hand side of constraint */
18051 SCIP_Real rhs /**< right hand side of constraint */
18052 )
18053{
18054 assert(scip != NULL);
18055
18056 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18058
18059 return SCIP_OKAY;
18060}
18061
18062/** creates by copying and captures a linear constraint */
18064 SCIP* scip, /**< target SCIP data structure */
18065 SCIP_CONS** cons, /**< pointer to store the created target constraint */
18066 SCIP* sourcescip, /**< source SCIP data structure */
18067 const char* name, /**< name of constraint */
18068 int nvars, /**< number of variables in source variable array */
18069 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18070 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18071 SCIP_Real lhs, /**< left hand side of the linear constraint */
18072 SCIP_Real rhs, /**< right hand side of the linear constraint */
18073 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18074 * variables of the target SCIP */
18075 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18076 * target constraints */
18077 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18078 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18079 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18080 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18081 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18082 SCIP_Bool local, /**< is constraint only valid locally? */
18083 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18084 SCIP_Bool dynamic, /**< is constraint subject to aging? */
18085 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18086 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18087 * if it may be moved to a more global node? */
18088 SCIP_Bool global, /**< create a global or a local copy? */
18089 SCIP_Bool* valid /**< pointer to store if the copying was valid */
18090 )
18091{
18092 SCIP_VAR** vars;
18093 SCIP_Real* coefs;
18094
18095 SCIP_Real constant;
18096 int requiredsize;
18097 int v;
18098 SCIP_Bool success;
18099
18100 if( SCIPisGT(scip, lhs, rhs) )
18101 {
18102 *valid = FALSE;
18103 return SCIP_OKAY;
18104 }
18105
18106 (*valid) = TRUE;
18107
18108 if( nvars == 0 )
18109 {
18110 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18111 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18112 return SCIP_OKAY;
18113 }
18114
18115 /* duplicate variable array */
18116 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
18117
18118 /* duplicate coefficient array */
18119 if( sourcecoefs != NULL )
18120 {
18121 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18122 }
18123 else
18124 {
18125 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18126 for( v = 0; v < nvars; ++v )
18127 coefs[v] = 1.0;
18128 }
18129
18130 constant = 0.0;
18131
18132 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18133 * the target SCIP
18134 */
18135 if( !SCIPvarIsOriginal(vars[0]) )
18136 {
18137 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18138
18139 if( requiredsize > nvars )
18140 {
18141 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18142 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18143
18144 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18145 assert(requiredsize <= nvars);
18146 }
18147 }
18148 else
18149 {
18150 for( v = 0; v < nvars; ++v )
18151 {
18152 assert(SCIPvarIsOriginal(vars[v]));
18153 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18154 assert(vars[v] != NULL);
18155 }
18156 }
18157
18158 success = TRUE;
18159 /* map variables of the source constraint to variables of the target SCIP */
18160 for( v = 0; v < nvars && success; ++v )
18161 {
18162 SCIP_VAR* var;
18163 var = vars[v];
18164
18165 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18166 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18167
18168 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18169 assert(!(success) || vars[v] != NULL);
18170 }
18171
18172 /* only create the target constraint, if all variables could be copied */
18173 if( success )
18174 {
18175 if( !SCIPisInfinity(scip, -lhs) )
18176 lhs -= constant;
18177
18178 if( !SCIPisInfinity(scip, rhs) )
18179 rhs -= constant;
18180
18181 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18182 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18183 }
18184 else
18185 *valid = FALSE;
18186
18187 /* free buffer array */
18188 SCIPfreeBufferArray(scip, &coefs);
18189 SCIPfreeBufferArray(scip, &vars);
18190
18191 return SCIP_OKAY;
18192}
18193
18194/** adds coefficient to linear constraint (if it is not zero) */
18196 SCIP* scip, /**< SCIP data structure */
18197 SCIP_CONS* cons, /**< constraint data */
18198 SCIP_VAR* var, /**< variable of constraint entry */
18199 SCIP_Real val /**< coefficient of constraint entry */
18200 )
18201{
18202 assert(scip != NULL);
18203 assert(cons != NULL);
18204 assert(var != NULL);
18205
18206 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18207 {
18208 SCIPerrorMessage("constraint is not linear\n");
18209 return SCIP_INVALIDDATA;
18210 }
18211
18212 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18213 * constraint after presolving we have to ensure that it holds active variables
18214 */
18216 {
18217 SCIP_CONSDATA* consdata;
18218 SCIP_VAR** consvars;
18219 SCIP_Real* consvals;
18220 SCIP_Real constant = 0.0;
18221 SCIP_Real rhs;
18222 SCIP_Real lhs;
18223 int nconsvars;
18224 int requiredsize;
18225 int v;
18226
18227 nconsvars = 1;
18228 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18229 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18230 consvars[0] = var;
18231 consvals[0] = val;
18232
18233 /* get active variables for new constraint */
18234 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18235
18236 /* if space was not enough we need to resize the buffers */
18237 if( requiredsize > nconsvars )
18238 {
18239 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18240 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18241
18242 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18243 assert(requiredsize <= nconsvars);
18244 }
18245
18246 consdata = SCIPconsGetData(cons);
18247 assert(consdata != NULL);
18248
18249 lhs = consdata->lhs;
18250 rhs = consdata->rhs;
18251
18252 /* adjust sides and check that we do not subtract infinity values */
18253 /* constant is infinite */
18254 if( SCIPisInfinity(scip, REALABS(constant)) )
18255 {
18256 if( constant < 0.0 )
18257 {
18258 if( SCIPisInfinity(scip, lhs) )
18259 {
18260 SCIPfreeBufferArray(scip, &consvals);
18261 SCIPfreeBufferArray(scip, &consvars);
18262
18263 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));
18264
18265 SCIPABORT();
18266 return SCIP_INVALIDDATA; /*lint !e527*/
18267 }
18268 if( SCIPisInfinity(scip, rhs) )
18269 {
18270 SCIPfreeBufferArray(scip, &consvals);
18271 SCIPfreeBufferArray(scip, &consvars);
18272
18273 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));
18274
18275 SCIPABORT();
18276 return SCIP_INVALIDDATA; /*lint !e527*/
18277 }
18278
18279 lhs = -SCIPinfinity(scip);
18280 rhs = -SCIPinfinity(scip);
18281 }
18282 else
18283 {
18284 if( SCIPisInfinity(scip, -lhs) )
18285 {
18286 SCIPfreeBufferArray(scip, &consvals);
18287 SCIPfreeBufferArray(scip, &consvars);
18288
18289 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));
18290
18291 SCIPABORT();
18292 return SCIP_INVALIDDATA; /*lint !e527*/
18293 }
18294 if( SCIPisInfinity(scip, -rhs) )
18295 {
18296 SCIPfreeBufferArray(scip, &consvals);
18297 SCIPfreeBufferArray(scip, &consvars);
18298
18299 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));
18300
18301 SCIPABORT();
18302 return SCIP_INVALIDDATA; /*lint !e527*/
18303 }
18304
18305 lhs = SCIPinfinity(scip);
18306 rhs = SCIPinfinity(scip);
18307 }
18308 }
18309 /* constant is not infinite */
18310 else
18311 {
18312 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18313 lhs -= constant;
18314 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18315 rhs -= constant;
18316
18317 if( SCIPisInfinity(scip, -lhs) )
18318 lhs = -SCIPinfinity(scip);
18319 else if( SCIPisInfinity(scip, lhs) )
18320 lhs = SCIPinfinity(scip);
18321
18322 if( SCIPisInfinity(scip, rhs) )
18323 rhs = SCIPinfinity(scip);
18324 else if( SCIPisInfinity(scip, -rhs) )
18325 rhs = -SCIPinfinity(scip);
18326 }
18327
18328 /* add all active variables to constraint */
18329 for( v = nconsvars - 1; v >= 0; --v )
18330 {
18331 if( !SCIPisZero(scip, consvals[v]) )
18332 {
18333 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18334 }
18335 }
18336
18337 /* update left and right hand sides */
18338 SCIP_CALL( chgLhs(scip, cons, lhs));
18339 SCIP_CALL( chgRhs(scip, cons, rhs));
18340
18341 SCIPfreeBufferArray(scip, &consvals);
18342 SCIPfreeBufferArray(scip, &consvars);
18343 }
18344 else if( !SCIPisZero(scip, val) )
18345 {
18346 SCIP_CALL( addCoef(scip, cons, var, val) );
18347 }
18348
18349 return SCIP_OKAY;
18350}
18351
18352/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18353 * not yet contained in the constraint
18354 *
18355 * @note This method may only be called during problem creation stage for an original constraint and variable.
18356 *
18357 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18358 */
18360 SCIP* scip, /**< SCIP data structure */
18361 SCIP_CONS* cons, /**< constraint data */
18362 SCIP_VAR* var, /**< variable of constraint entry */
18363 SCIP_Real val /**< new coefficient of constraint entry */
18364 )
18365{
18366 SCIP_CONSDATA* consdata;
18367 SCIP_VAR** vars;
18368 SCIP_Bool found;
18369 int i;
18370
18371 assert(scip != NULL);
18372 assert(cons != NULL);
18373 assert(var != NULL);
18374
18375 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18376 {
18377 SCIPerrorMessage("constraint is not linear\n");
18378 return SCIP_INVALIDDATA;
18379 }
18380
18382 {
18383 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18384 return SCIP_INVALIDDATA;
18385 }
18386
18387 consdata = SCIPconsGetData(cons);
18388 assert(consdata != NULL);
18389
18390 vars = consdata->vars;
18391 found = FALSE;
18392 i = 0;
18393 while( i < consdata->nvars )
18394 {
18395 if( vars[i] == var )
18396 {
18397 if( found || SCIPisZero(scip, val) )
18398 {
18399 SCIP_CALL( delCoefPos(scip, cons, i) );
18400
18401 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18402 i--;
18403 }
18404 else
18405 {
18406 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18407 }
18408 found = TRUE;
18409 }
18410 i++;
18411 }
18412
18413 if( !found )
18414 {
18415 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18416 }
18417
18418 return SCIP_OKAY;
18419}
18420
18421/** deletes variable from linear constraint
18422 *
18423 * @note This method may only be called during problem creation stage for an original constraint and variable.
18424 *
18425 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18426 */
18428 SCIP* scip, /**< SCIP data structure */
18429 SCIP_CONS* cons, /**< constraint data */
18430 SCIP_VAR* var /**< variable of constraint entry */
18431 )
18432{
18433 assert(scip != NULL);
18434 assert(cons != NULL);
18435 assert(var != NULL);
18436
18437 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18438
18439 return SCIP_OKAY;
18440}
18441
18442/** gets left hand side of linear constraint */
18444 SCIP* scip, /**< SCIP data structure */
18445 SCIP_CONS* cons /**< constraint data */
18446 )
18447{
18448 SCIP_CONSDATA* consdata;
18449
18450 assert(scip != NULL);
18451 assert(cons != NULL);
18452
18453 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18454 {
18455 SCIPerrorMessage("constraint is not linear\n");
18456 SCIPABORT();
18457 return SCIP_INVALID; /*lint !e527*/
18458 }
18459
18460 consdata = SCIPconsGetData(cons);
18461 assert(consdata != NULL);
18462
18463 return consdata->lhs;
18464}
18465
18466/** gets right hand side of linear constraint */
18468 SCIP* scip, /**< SCIP data structure */
18469 SCIP_CONS* cons /**< constraint data */
18470 )
18471{
18472 SCIP_CONSDATA* consdata;
18473
18474 assert(scip != NULL);
18475 assert(cons != NULL);
18476
18477 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18478 {
18479 SCIPerrorMessage("constraint is not linear\n");
18480 SCIPABORT();
18481 return SCIP_INVALID; /*lint !e527*/
18482 }
18483
18484 consdata = SCIPconsGetData(cons);
18485 assert(consdata != NULL);
18486
18487 return consdata->rhs;
18488}
18489
18490/** changes left hand side of linear constraint */
18492 SCIP* scip, /**< SCIP data structure */
18493 SCIP_CONS* cons, /**< constraint data */
18494 SCIP_Real lhs /**< new left hand side */
18495 )
18496{
18497 assert(scip != NULL);
18498 assert(cons != NULL);
18499
18500 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18501 {
18502 SCIPerrorMessage("constraint is not linear\n");
18503 return SCIP_INVALIDDATA;
18504 }
18505
18506 SCIP_CALL( chgLhs(scip, cons, lhs) );
18507
18508 return SCIP_OKAY;
18509}
18510
18511/** changes right hand side of linear constraint */
18513 SCIP* scip, /**< SCIP data structure */
18514 SCIP_CONS* cons, /**< constraint data */
18515 SCIP_Real rhs /**< new right hand side */
18516 )
18517{
18518 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18519 {
18520 SCIPerrorMessage("constraint is not linear\n");
18521 return SCIP_INVALIDDATA;
18522 }
18523
18524 SCIP_CALL( chgRhs(scip, cons, rhs) );
18525
18526 return SCIP_OKAY;
18527}
18528
18529/** gets the number of variables in the 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 -1; /*lint !e527*/
18545 }
18546
18547 consdata = SCIPconsGetData(cons);
18548 assert(consdata != NULL);
18549
18550 return consdata->nvars;
18551}
18552
18553/** gets the array of variables in the linear constraint; the user must not modify this array! */
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 NULL; /*lint !e527*/
18569 }
18570
18571 consdata = SCIPconsGetData(cons);
18572 assert(consdata != NULL);
18573
18574 return consdata->vars;
18575}
18576
18577/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18579 SCIP* scip, /**< SCIP data structure */
18580 SCIP_CONS* cons /**< constraint data */
18581 )
18582{
18583 SCIP_CONSDATA* consdata;
18584
18585 assert(scip != NULL);
18586 assert(cons != NULL);
18587
18588 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18589 {
18590 SCIPerrorMessage("constraint is not linear\n");
18591 SCIPABORT();
18592 return NULL; /*lint !e527*/
18593 }
18594
18595 consdata = SCIPconsGetData(cons);
18596 assert(consdata != NULL);
18597
18598 return consdata->vals;
18599}
18600
18601/** gets the activity of the linear constraint in the given solution
18602 *
18603 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18604 * comprises positive and negative infinity contributions
18605 */
18607 SCIP* scip, /**< SCIP data structure */
18608 SCIP_CONS* cons, /**< constraint data */
18609 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18610 )
18611{
18612 SCIP_CONSDATA* consdata;
18613
18614 assert(scip != NULL);
18615 assert(cons != NULL);
18616
18617 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18618 {
18619 SCIPerrorMessage("constraint is not linear\n");
18620 SCIPABORT();
18621 return SCIP_INVALID; /*lint !e527*/
18622 }
18623
18624 consdata = SCIPconsGetData(cons);
18625 assert(consdata != NULL);
18626
18627 if( consdata->row != NULL )
18628 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18629 else
18630 return consdataGetActivity(scip, consdata, sol);
18631}
18632
18633/** gets the feasibility of the linear constraint in the given solution */
18635 SCIP* scip, /**< SCIP data structure */
18636 SCIP_CONS* cons, /**< constraint data */
18637 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18638 )
18639{
18640 SCIP_CONSDATA* consdata;
18641
18642 assert(scip != NULL);
18643 assert(cons != NULL);
18644
18645 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18646 {
18647 SCIPerrorMessage("constraint is not linear\n");
18648 SCIPABORT();
18649 return SCIP_INVALID; /*lint !e527*/
18650 }
18651
18652 consdata = SCIPconsGetData(cons);
18653 assert(consdata != NULL);
18654
18655 if( consdata->row != NULL )
18656 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18657 else
18658 return consdataGetFeasibility(scip, consdata, sol);
18659}
18660
18661/** gets the dual solution of the linear constraint in the current LP */
18663 SCIP* scip, /**< SCIP data structure */
18664 SCIP_CONS* cons /**< constraint data */
18665 )
18666{
18667 SCIP_CONSDATA* consdata;
18668
18669 assert(scip != NULL);
18670 assert(cons != NULL);
18671 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18672
18673 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18674 {
18675 SCIPerrorMessage("constraint is not linear\n");
18676 SCIPABORT();
18677 return SCIP_INVALID; /*lint !e527*/
18678 }
18679
18680 consdata = SCIPconsGetData(cons);
18681 assert(consdata != NULL);
18682
18683 if( consdata->row != NULL )
18684 return SCIProwGetDualsol(consdata->row);
18685 else
18686 return 0.0;
18687}
18688
18689/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18691 SCIP* scip, /**< SCIP data structure */
18692 SCIP_CONS* cons /**< constraint data */
18693 )
18694{
18695 SCIP_CONSDATA* consdata;
18696
18697 assert(scip != NULL);
18698 assert(cons != NULL);
18699 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18700
18701 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18702 {
18703 SCIPerrorMessage("constraint is not linear\n");
18704 SCIPABORT();
18705 return SCIP_INVALID; /*lint !e527*/
18706 }
18707
18708 consdata = SCIPconsGetData(cons);
18709 assert(consdata != NULL);
18710
18711 if( consdata->row != NULL )
18712 return SCIProwGetDualfarkas(consdata->row);
18713 else
18714 return 0.0;
18715}
18716
18717/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18718 * the user must not modify the row!
18719 */
18721 SCIP* scip, /**< SCIP data structure */
18722 SCIP_CONS* cons /**< constraint data */
18723 )
18724{
18725 SCIP_CONSDATA* consdata;
18726
18727 assert(scip != NULL);
18728 assert(cons != NULL);
18729
18730 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18731 {
18732 SCIPerrorMessage("constraint is not linear\n");
18733 SCIPABORT();
18734 return NULL; /*lint !e527*/
18735 }
18736
18737 consdata = SCIPconsGetData(cons);
18738 assert(consdata != NULL);
18739
18740 return consdata->row;
18741}
18742
18743/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18745 SCIP* scip, /**< SCIP data structure */
18746 SCIP_CONS* cons, /**< source constraint to try to convert */
18747 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18748 )
18749{
18750 SCIP_CONSHDLR* conshdlr;
18751 SCIP_CONSHDLRDATA* conshdlrdata;
18752 SCIP_CONSDATA* consdata;
18753 SCIP_VAR* var;
18754 SCIP_Real val;
18755 SCIP_Real lb;
18756 SCIP_Real ub;
18757 SCIP_Real poscoeffsum;
18758 SCIP_Real negcoeffsum;
18759 SCIP_Bool infeasible;
18760 SCIP_Bool integral;
18761 int nchgsides = 0;
18762 int nposbin;
18763 int nnegbin;
18764 int nposint;
18765 int nnegint;
18766 int nposimpl;
18767 int nnegimpl;
18768 int nposimplbin;
18769 int nnegimplbin;
18770 int nposcont;
18771 int nnegcont;
18772 int ncoeffspone;
18773 int ncoeffsnone;
18774 int ncoeffspint;
18775 int ncoeffsnint;
18776 int ncoeffspfrac;
18777 int ncoeffsnfrac;
18778 int i;
18779
18780 assert(scip != NULL);
18781 assert(cons != NULL);
18782 assert(upgdcons != NULL);
18783
18784 *upgdcons = NULL;
18785
18786 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18787 if( SCIPconsIsModifiable(cons) )
18788 return SCIP_OKAY;
18789
18790 /* check for upgradability */
18791 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18792 return SCIP_OKAY;
18793
18794 /* get the constraint handler and check, if it's really a linear constraint */
18795 conshdlr = SCIPconsGetHdlr(cons);
18796 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18797 {
18798 SCIPerrorMessage("constraint is not linear\n");
18799 return SCIP_INVALIDDATA;
18800 }
18801
18802 /* get constraint handler data and constraint data */
18803 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18804 assert(conshdlrdata != NULL);
18805 consdata = SCIPconsGetData(cons);
18806 assert(consdata != NULL);
18807
18808 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18809 if( consdata->upgraded )
18810 return SCIP_OKAY;
18811
18812 /* check, if the constraint is already stored as LP row */
18813 if( consdata->row != NULL )
18814 {
18815 if( SCIProwIsInLP(consdata->row) )
18816 {
18817 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18818 return SCIP_INVALIDDATA;
18819 }
18820 else
18821 {
18822 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18823 }
18824 }
18825
18826 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18827
18828 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18829 * skipped and we hope that the infeasibility gets detected later again.
18830 *
18831 * TODO: do we want to try to upgrade the constraint anyway?
18832 *
18833 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18834 * proven to be infeasible.
18835 */
18836 if( infeasible ) /*lint !e774*/
18837 return SCIP_OKAY;
18838
18839 /* tighten sides */
18840 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18841
18842 if( infeasible ) /*lint !e774*/
18843 return SCIP_OKAY;
18844
18845 /*
18846 * calculate some statistics on linear constraint
18847 */
18848
18849 nposbin = 0;
18850 nnegbin = 0;
18851 nposint = 0;
18852 nnegint = 0;
18853 nposimpl = 0;
18854 nnegimpl = 0;
18855 nposimplbin = 0;
18856 nnegimplbin = 0;
18857 nposcont = 0;
18858 nnegcont = 0;
18859 ncoeffspone = 0;
18860 ncoeffsnone = 0;
18861 ncoeffspint = 0;
18862 ncoeffsnint = 0;
18863 ncoeffspfrac = 0;
18864 ncoeffsnfrac = 0;
18865 integral = TRUE;
18866 poscoeffsum = 0.0;
18867 negcoeffsum = 0.0;
18868
18869 for( i = 0; i < consdata->nvars; ++i )
18870 {
18871 var = consdata->vars[i];
18872 val = consdata->vals[i];
18873 lb = SCIPvarGetLbLocal(var);
18874 ub = SCIPvarGetUbLocal(var);
18875 assert(!SCIPisZero(scip, val));
18876
18877 switch( SCIPvarGetType(var) )
18878 {
18880 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18881 integral = integral && SCIPisIntegral(scip, val);
18882 if( val >= 0.0 )
18883 nposbin++;
18884 else
18885 nnegbin++;
18886 break;
18888 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18889 integral = integral && SCIPisIntegral(scip, val);
18890 if( val >= 0.0 )
18891 nposint++;
18892 else
18893 nnegint++;
18894 break;
18896 if( SCIPvarIsBinary(var) )
18897 {
18898 if( val >= 0.0 )
18899 nposimplbin++;
18900 else
18901 nnegimplbin++;
18902 }
18903 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18904 integral = integral && SCIPisIntegral(scip, val);
18905 if( val >= 0.0 )
18906 nposimpl++;
18907 else
18908 nnegimpl++;
18909 break;
18911 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18912 if( val >= 0.0 )
18913 nposcont++;
18914 else
18915 nnegcont++;
18916 break;
18917 default:
18918 SCIPerrorMessage("unknown variable type\n");
18919 return SCIP_INVALIDDATA;
18920 }
18921 if( SCIPisEQ(scip, val, 1.0) )
18922 ncoeffspone++;
18923 else if( SCIPisEQ(scip, val, -1.0) )
18924 ncoeffsnone++;
18925 else if( SCIPisIntegral(scip, val) )
18926 {
18927 if( SCIPisPositive(scip, val) )
18928 ncoeffspint++;
18929 else
18930 ncoeffsnint++;
18931 }
18932 else
18933 {
18934 if( SCIPisPositive(scip, val) )
18935 ncoeffspfrac++;
18936 else
18937 ncoeffsnfrac++;
18938 }
18939 if( SCIPisPositive(scip, val) )
18940 poscoeffsum += val;
18941 else
18942 negcoeffsum += val;
18943 }
18944
18945 /*
18946 * call the upgrading methods
18947 */
18948
18949 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18950 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18951 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",
18952 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18953 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18954 poscoeffsum, negcoeffsum, integral);
18955
18956 /* try all upgrading methods in priority order in case the upgrading step is enable */
18957 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18958 {
18959 if( conshdlrdata->linconsupgrades[i]->active )
18960 {
18961 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18962 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18963 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18964 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18965 poscoeffsum, negcoeffsum, integral,
18966 upgdcons) );
18967 }
18968 }
18969
18970#ifdef SCIP_DEBUG
18971 if( *upgdcons != NULL )
18972 {
18974 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18975 SCIPdebugPrintCons(scip, *upgdcons, NULL);
18976 }
18977#endif
18978
18979 return SCIP_OKAY; /*lint !e438*/
18980}
18981
18982/** cleans up (multi-)aggregations and fixings from linear constraints */
18984 SCIP* scip, /**< SCIP data structure */
18985 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18986 SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
18987 )
18988{
18989 SCIP_CONSHDLR* conshdlr;
18990 SCIP_CONS** conss;
18991 int nconss;
18992 int i;
18993
18994 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18995 if( conshdlr == NULL )
18996 return SCIP_OKAY;
18997
18998 assert(infeasible != NULL);
18999 *infeasible = FALSE;
19000
19001 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
19002 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
19003
19004 for( i = 0; i < nconss; ++i )
19005 {
19006 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
19007
19008 if( *infeasible )
19009 break;
19010 }
19011
19012 return SCIP_OKAY;
19013}
static long bound
SCIP_VAR * w
Definition: circlepacking.c:67
SCIP_VAR * a
Definition: circlepacking.c:66
SCIP_VAR ** b
Definition: circlepacking.c:65
SCIP_VAR ** x
Definition: circlepacking.c:63
enum Proprule PROPRULE
Definition: cons_and.c:179
Proprule
Definition: cons_and.c:172
struct InferInfo INFERINFO
Constraint handler for knapsack constraints of the form , x binary and .
#define MAX_CLIQUE_NONZEROS_PER_CONS
Definition: cons_linear.c:7858
enum Proprule PROPRULE
Definition: cons_linear.c:355
static SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3670
#define DEFAULT_AGGREGATEVARIABLES
Definition: cons_linear.c:142
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linear.c:1101
#define DEFAULT_NMINCOMPARISONS
Definition: cons_linear.c:127
#define DEFAULT_MULTAGGRREMOVE
Definition: cons_linear.c:161
#define DEFAULT_DUALPRESOLVING
Definition: cons_linear.c:144
#define DEFAULT_EXTRACTCLIQUES
Definition: cons_linear.c:165
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3269
#define CONSHDLR_NEEDSCONS
Definition: cons_linear.c:108
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1548
#define CONSHDLR_SEPAFREQ
Definition: cons_linear.c:101
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:7169
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7453
#define CONFLICTHDLR_PRIORITY
Definition: cons_linear.c:118
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
Definition: cons_linear.c:2586
static SCIP_DECL_EVENTEXEC(eventExecLinear)
static SCIP_RETCODE convertEquality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgvartypes)
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define CONFLICTHDLR_NAME
Definition: cons_linear.c:116
#define MAXDNOM
Definition: cons_linear.c:167
static SCIP_RETCODE conshdlrdataIncludeUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_LINCONSUPGRADE *linconsupgrade)
Definition: cons_linear.c:619
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:7925
static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
#define CONSHDLR_CHECKPRIORITY
Definition: cons_linear.c:100
#define CONSHDLR_DESC
Definition: cons_linear.c:97
static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7429
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
Definition: cons_linear.c:3160
static int getVarWeight(SCIP_VAR *var)
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9496
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1311
static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
static SCIP_DECL_CONSPRESOL(consPresolLinear)
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
Definition: cons_linear.c:4990
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
static SCIP_DECL_CONSFREE(consFreeLinear)
#define DEFAULT_DETECTCUTOFFBOUND
Definition: cons_linear.c:148
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:5321
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds, int *nchgvartypes)
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss, int *nchgvartypes)
Definition: cons_linear.c:9608
static SCIP_DECL_CONSINITLP(consInitlpLinear)
#define CONSHDLR_PROP_TIMING
Definition: cons_linear.c:111
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1258
static SCIP_DECL_CONSPARSE(consParseLinear)
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:448
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
static SCIP_RETCODE retrieveParallelConstraints(SCIP_HASHTABLE *hashtable, SCIP_CONS **querycons, SCIP_CONS **parallelconss, int *nparallelconss)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:117
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linear.c:567
static void calculateMinvalAndMaxval(SCIP *scip, SCIP_Real side, SCIP_Real val, SCIP_Real minresactivity, SCIP_Real maxresactivity, SCIP_Real *minval, SCIP_Real *maxval)
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:651
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1365
static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
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:2027
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
Definition: cons_linear.c:8898
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2052
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:2002
#define CONSHDLR_MAXPREROUNDS
Definition: cons_linear.c:105
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
Definition: cons_linear.c:589
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
Definition: cons_linear.c:3918
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1338
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
Definition: cons_linear.c:508
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_linear.c:125
#define DEFAULT_MAXAGGRNORMSCALE
Definition: cons_linear.c:134
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
Definition: cons_linear.c:4101
#define checkMaxActivityDelta(scip, consdata)
Definition: cons_linear.c:1543
static SCIP_DECL_CONSTRANS(consTransLinear)
#define CONSHDLR_SEPAPRIORITY
Definition: cons_linear.c:98
static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
#define DEFAULT_SINGLETONSTUFFING
Definition: cons_linear.c:145
#define DEFAULT_MAXROUNDSROOT
Definition: cons_linear.c:122
static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
Definition: cons_linear.c:3115
#define MINVALRECOMP
Definition: cons_linear.c:177
#define DEFAULT_MAXCARDBOUNDDIST
Definition: cons_linear.c:138
#define DEFAULT_MAXEASYACTIVITYDELTA
Definition: cons_linear.c:136
static SCIP_DECL_CONSEXIT(consExitLinear)
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
Definition: cons_linear.c:4008
static int inferInfoGetPos(INFERINFO inferinfo)
Definition: cons_linear.c:405
static SCIP_DECL_CONSPRINT(consPrintLinear)
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides)
#define DEFAULT_CHECKRELMAXABS
Definition: cons_linear.c:132
#define DEFAULT_MAXDUALMULTAGGRQUOT
Definition: cons_linear.c:164
static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
Definition: cons_linear.c:529
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)
static SCIP_DECL_CONSENFOPS(consEnfopsLinear)
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:5199
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
Definition: cons_linear.c:5726
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:374
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4480
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:7552
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
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:2539
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1472
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
Definition: cons_linear.c:3412
static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
#define DEFAULT_SORTVARS
Definition: cons_linear.c:130
#define DEFAULT_MAXMULTAGGRQUOT
Definition: cons_linear.c:163
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2075
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:718
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1443
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:4808
#define MAXCONSPRESOLROUNDS
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_linear.c:473
#define MAXACTVAL
Definition: cons_linear.c:172
#define NONLINCONSUPGD_PRIORITY
Definition: cons_linear.c:180
#define DEFAULT_MAXSEPACUTSROOT
Definition: cons_linear.c:124
@ PROPRULE_1_RANGEDROW
Definition: cons_linear.c:351
@ PROPRULE_1_LHS
Definition: cons_linear.c:349
@ PROPRULE_INVALID
Definition: cons_linear.c:353
@ PROPRULE_1_RHS
Definition: cons_linear.c:347
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:6991
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1419
#define DEFAULT_RANGEDROWPROPAGATION
Definition: cons_linear.c:156
static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:823
static SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_linear.c:126
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3026
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:9020
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4160
static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
static SCIP_RETCODE presolStuffing(SCIP *scip, SCIP_CONS *cons, SCIP_Bool singletonstuffing, SCIP_Bool singlevarstuffing, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds)
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:684
static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3140
static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5055
static SCIP_DECL_CONSINIT(consInitLinear)
#define DEFAULT_RANGEDROWFREQ
Definition: cons_linear.c:159
static SCIP_DECL_CONSDELETE(consDeleteLinear)
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:7642
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2174
#define DEFAULT_RANGEDROWARTCONS
Definition: cons_linear.c:157
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3805
#define MAXSCALEDCOEFINTEGER
Definition: cons_linear.c:169
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2098
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:2351
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:854
static SCIP_DECL_CONSACTIVE(consActiveLinear)
#define BINWEIGHT
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
Definition: cons_linear.c:3540
static SCIP_DECL_CONSCHECK(consCheckLinear)
#define DEFAULT_SIMPLIFYINEQUALITIES
Definition: cons_linear.c:143
static SCIP_DECL_CONSSEPALP(consSepalpLinear)
#define CONSHDLR_PROPFREQ
Definition: cons_linear.c:102
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5391
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:1610
static unsigned int getParallelConsKey(SCIP_CONS *cons)
#define CONTWEIGHT
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:7790
#define CONSHDLR_PRESOLTIMING
Definition: cons_linear.c:110
#define DEFAULT_DETECTPARTIALOBJECTIVE
Definition: cons_linear.c:154
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linear.c:1060
static SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
#define DEFAULT_MAXSEPACUTS
Definition: cons_linear.c:123
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:2667
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2255
static SCIP_DECL_CONSINITSOL(consInitsolLinear)
static SCIP_DECL_CONSRESPROP(consRespropLinear)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7516
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
Definition: cons_linear.c:1140
#define CONSHDLR_EAGERFREQ
Definition: cons_linear.c:103
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:2446
#define DEFAULT_TIGHTENBOUNDSFREQ
Definition: cons_linear.c:120
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
Definition: cons_linear.c:9554
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9440
static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
Definition: cons_linear.c:2239
#define EVENTHDLR_DESC
Definition: cons_linear.c:114
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:543
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1392
static SCIP_DECL_CONSPROP(consPropLinear)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4543
static SCIP_DECL_CONSLOCK(consLockLinear)
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2289
#define DEFAULT_MAXROUNDS
Definition: cons_linear.c:121
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:2876
#define CONSHDLR_ENFOPRIORITY
Definition: cons_linear.c:99
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:5251
static int getInferInt(PROPRULE proprule, int pos)
Definition: cons_linear.c:433
static int inferInfoGetProprule(INFERINFO inferinfo)
Definition: cons_linear.c:396
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgvartypes)
#define DEFAULT_MINGAINPERNMINCOMP
Definition: cons_linear.c:128
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3094
static SCIP_RETCODE rangedRowSimplify(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars)
#define CONSHDLR_DELAYSEPA
Definition: cons_linear.c:106
static SCIP_DECL_CONSCOPY(consCopyLinear)
#define MAXSCALEDCOEF
Definition: cons_linear.c:168
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1212
#define DEFAULT_RANGEDROWMAXDEPTH
Definition: cons_linear.c:158
static SCIP_RETCODE analyzeConflictRangedRow(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5668
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:757
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:6711
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2271
#define CONSHDLR_NAME
Definition: cons_linear.c:96
static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
static int inferInfoToInt(INFERINFO inferinfo)
Definition: cons_linear.c:387
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 consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3345
#define DEFAULT_SINGLEVARSTUFFING
Definition: cons_linear.c:146
#define EVENTHDLR_NAME
Definition: cons_linear.c:113
#define INTWEIGHT
static SCIP_RETCODE checkParallelObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides, SCIP_Bool *infeasible)
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:791
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:5106
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:151
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
#define MAXVALRECOMP
Definition: cons_linear.c:176
#define CONSHDLR_DELAYPROP
Definition: cons_linear.c:107
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:2816
static SCIP_Bool canTightenBounds(SCIP_CONS *cons)
Definition: cons_linear.c:5223
#define DEFAULT_SEPARATEALL
Definition: cons_linear.c:140
static void findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Definition: cons_linear.c:414
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:6987
Constraint handler for linear constraints in their most general form, .
constraint handler for nonlinear constraints specified by algebraic expressions
defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
#define QUAD_MEMBER(x)
Definition: dbldblarith.h:48
#define SCIPquadprecSumQD(r, a, b)
Definition: dbldblarith.h:62
#define QUAD_ASSIGN(a, constant)
Definition: dbldblarith.h:51
#define QUAD(x)
Definition: dbldblarith.h:47
#define QUAD_ASSIGN_Q(a, b)
Definition: dbldblarith.h:52
#define QUAD_TO_DBL(x)
Definition: dbldblarith.h:49
methods for debugging
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:299
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:298
#define NULL
Definition: def.h:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#define COPYSIGN
Definition: def.h:257
#define SCIP_Longint
Definition: def.h:157
#define SCIP_MAXTREEDEPTH
Definition: def.h:315
#define SCIP_REAL_MAX
Definition: def.h:173
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:242
#define MAX3(x, y, z)
Definition: def.h:246
#define SCIP_Real
Definition: def.h:172
#define ABS(x)
Definition: def.h:234
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL_ABORT(x)
Definition: def.h:352
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define MIN3(x, y, z)
Definition: def.h:250
#define SCIPABORT()
Definition: def.h:345
#define REALABS(x)
Definition: def.h:196
#define EPSGT(x, y, eps)
Definition: def.h:200
#define SCIP_CALL(x)
Definition: def.h:373
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_RETCODE SCIPincludeConsUpgradeNonlinear(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nlconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
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_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts)
SCIP_Real SCIPgetRhsNonlinear(SCIP_CONS *cons)
SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
#define SCIP_DECL_LINCONSUPGD(x)
Definition: cons_linear.h:120
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 SCIPcleanupConssLinear(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_Real SCIPgetFeasibilityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip_copy.c:2068
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip_copy.c:660
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_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:606
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip_general.c:643
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:734
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:390
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2220
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1668
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2172
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3089
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1268
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2843
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3043
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2349
#define SCIPhashFour(a, b, c, d)
Definition: pub_misc.h:556
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2582
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:2299
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2611
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2807
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2680
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2550
#define SCIPhashSignature64(a)
Definition: pub_misc.h:549
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip_prob.c:3697
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3475
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:3586
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3229
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3394
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsgPrint
Definition: scip_message.h:79
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:88
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9124
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9376
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9397
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9827
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11215
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
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
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
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:269
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10399
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:428
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4656
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:808
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4227
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4613
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:540
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip_cons.c:396
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:831
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_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 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
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip_cons.c:693
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
Definition: scip_cons.c:900
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:323
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5140
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4636
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4197
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip_cons.c:420
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:516
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:941
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
Definition: scip_cons.c:924
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip_cons.c:468
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip_cons.c:762
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:624
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip_cons.c:444
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4217
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:647
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4670
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:854
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4593
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip_cons.c:670
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:785
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8244
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:8224
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8473
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8234
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8383
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2537
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8665
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip_cons.c:1297
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8423
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8513
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8413
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8343
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8523
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8563
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip_cons.c:1272
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition: scip_cons.c:1322
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition: cons.c:8607
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8403
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2043
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8275
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_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8433
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8453
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8573
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8214
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8553
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1813
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2015
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8463
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip_cons.c:1525
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8493
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1174
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip_cons.c:1372
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition: scip_cons.c:1347
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8393
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1785
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8483
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:250
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
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:324
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1030
SCIP_VARTYPE SCIPeventGetNewtype(SCIP_EVENT *event)
Definition: event.c:1283
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_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 SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1218
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1053
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1242
SCIP_VARTYPE SCIPeventGetOldtype(SCIP_EVENT *event)
Definition: event.c:1266
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:3860
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1453
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1552
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1431
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:3870
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1567
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:416
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:83
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:105
SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:424
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:396
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip_nlp.c:1058
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition: nlp.c:1956
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_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:97
void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
Definition: cons.c:8108
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition: cons.c:8076
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17411
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1583
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_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1701
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2212
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2167
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1562
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17325
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1607
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17523
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_lp.c:1727
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17312
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2144
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1213
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:137
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
int SCIPgetNSepaRounds(SCIP *scip)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
int SCIPgetNRuns(SCIP *scip)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Real SCIPgetHugeValue(SCIP *scip)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip_tree.c:146
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17640
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip_var.c:1738
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5326
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12794
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17660
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4474
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17902
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18210
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17914
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17768
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17619
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:7044
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1480
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17558
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3353
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip_var.c:8688
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18164
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8721
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17581
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:8524
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:5738
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17946
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5443
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17604
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip_var.c:1794
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18108
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17778
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4382
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4560
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2128
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17788
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17439
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:8658
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18700
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1248
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip_var.c:4768
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
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip_var.c:4736
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17630
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8299
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1693
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17878
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17866
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:6903
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17650
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18154
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17594
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17726
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
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17568
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18098
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8399
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:5624
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:1992
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11962
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip_var.c:230
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:4636
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip_var.c:343
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18690
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3295
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:1439
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1214
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition: scip_var.c:8752
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:5555
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17890
void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5541
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10880
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10869
SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
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 const SCIP_Real scalars[]
Definition: lp.c:5740
static const char * paramname[]
Definition: lpi_msk.c:5096
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
public methods for conflict analysis handlers
public methods for managing constraints
public methods for managing events
public functions to work with algebraic expressions
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPstatisticMessage
Definition: pub_message.h:123
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
#define SCIPdebugMessage
Definition: pub_message.h:96
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for problem variables
public methods for branching rule plugins and branching
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for cuts and aggregation rows
public methods for event handler plugins and event handlers
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
SCIP_DECL_LINCONSUPGD((*linconsupgd))
structs for symmetry computations
methods for dealing with symmetry detection graphs
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:60
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:64
@ SCIP_LINCONSTYPE_BINPACKING
Definition: type_cons.h:85
@ SCIP_LINCONSTYPE_VARBOUND
Definition: type_cons.h:78
@ SCIP_LINCONSTYPE_EMPTY
Definition: type_cons.h:73
@ SCIP_LINCONSTYPE_INVKNAPSACK
Definition: type_cons.h:83
@ SCIP_LINCONSTYPE_PRECEDENCE
Definition: type_cons.h:77
@ SCIP_LINCONSTYPE_AGGREGATION
Definition: type_cons.h:76
@ SCIP_LINCONSTYPE_MIXEDBINARY
Definition: type_cons.h:88
@ SCIP_LINCONSTYPE_SINGLETON
Definition: type_cons.h:75
@ SCIP_LINCONSTYPE_SETCOVERING
Definition: type_cons.h:81
@ SCIP_LINCONSTYPE_EQKNAPSACK
Definition: type_cons.h:84
@ SCIP_LINCONSTYPE_FREE
Definition: type_cons.h:74
@ SCIP_LINCONSTYPE_KNAPSACK
Definition: type_cons.h:86
@ SCIP_LINCONSTYPE_SETPARTITION
Definition: type_cons.h:79
@ SCIP_LINCONSTYPE_INTKNAPSACK
Definition: type_cons.h:87
@ SCIP_LINCONSTYPE_SETPACKING
Definition: type_cons.h:80
@ SCIP_LINCONSTYPE_GENERAL
Definition: type_cons.h:89
@ SCIP_LINCONSTYPE_CARDINALITY
Definition: type_cons.h:82
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition: type_cons.h:91
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:125
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:73
#define SCIP_EVENTTYPE_TYPECHANGED
Definition: type_event.h:86
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:76
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:120
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:79
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:72
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:71
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:152
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:75
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:124
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:121
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:122
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:151
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:123
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:77
@ SCIP_EXPRCURV_LINEAR
Definition: type_expr.h:65
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:57
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
@ SCIP_VERBLEVEL_HIGH
Definition: type_message.h:56
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_FEASIBLE
Definition: type_result.h:45
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_CONSADDED
Definition: type_result.h:52
@ SCIP_SEPARATED
Definition: type_result.h:49
@ SCIP_SUCCESS
Definition: type_result.h:58
@ SCIP_INFEASIBLE
Definition: type_result.h:46
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_READERROR
Definition: type_retcode.h:45
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PROBLEM
Definition: type_set.h:45
@ SCIP_STAGE_INITSOLVE
Definition: type_set.h:52
@ SCIP_STAGE_EXITPRESOLVE
Definition: type_set.h:50
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition: type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition: type_set.h:51
enum SYM_Symtype SYM_SYMTYPE
Definition: type_symmetry.h:64
@ SYM_SYMTYPE_SIGNPERM
Definition: type_symmetry.h:62
@ SYM_SYMTYPE_PERM
Definition: type_symmetry.h:61
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:54
#define NLOCKTYPES
Definition: type_var.h:94
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:63
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_IMPLINT
Definition: type_var.h:64
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:62
@ SCIP_VARSTATUS_ORIGINAL
Definition: type_var.h:49
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:52
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:51
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:54
@ SCIP_VARSTATUS_NEGATED
Definition: type_var.h:55
@ SCIP_VARSTATUS_AGGREGATED
Definition: type_var.h:53
@ SCIP_VARSTATUS_LOOSE
Definition: type_var.h:50
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:100
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:97
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:57