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 numerator;
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, &numerator, &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
7102#ifndef SCIP_DEBUG
7103 oldnchgbds = 0;
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 && consdata->nvars > 0 )
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 /* get the minimal and maximal activity of the constraint */
9064 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9065 &isminsettoinfinity, &ismaxsettoinfinity);
9066 assert(( isminsettoinfinity && !SCIPisInfinity(scip, -consdata->lhs) )
9067 || SCIPisLT(scip, minactivity, consdata->lhs)
9068 || ( ismaxsettoinfinity && !SCIPisInfinity(scip, consdata->rhs) )
9069 || SCIPisGT(scip, maxactivity, consdata->rhs));
9070
9071 minleftactivity = 0.0;
9072 maxleftactivity = 0.0;
9073
9074 /* try to tighten each coefficient */
9075 i = 0;
9076 while( i < consdata->nvars )
9077 {
9078 /* get coefficient and variable's bounds */
9079 var = consdata->vars[i];
9080 val = consdata->vals[i];
9081 assert(!SCIPisZero(scip, val));
9082 lb = SCIPvarGetLbLocal(var);
9083 ub = SCIPvarGetUbLocal(var);
9084
9085 /* check sign of coefficient */
9086 if( val >= 0.0 )
9087 {
9088 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9089 isvarrelevant[i] = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS
9090 && SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs);
9091
9092 if( isvarrelevant[i] )
9093 {
9094 /* change coefficients:
9095 * ai' := max(lhs - minact, maxact - rhs)
9096 * lhs' := lhs - (ai - ai')*li
9097 * rhs' := rhs - (ai - ai')*ui
9098 */
9099
9100 lval = consdata->lhs - minactivity;
9101 rval = maxactivity - consdata->rhs;
9102
9103 /* Try to avoid cancellation, if there are only two variables */
9104 if( consdata->nvars == 2 )
9105 {
9106 SCIP_Real otherval;
9107 otherval = consdata->vals[1-i];
9108
9109 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9110 {
9111 lval = consdata->lhs - val*lb;
9112 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9113 }
9114
9115 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9116 {
9117 rval = val*ub - consdata->rhs;
9118 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9119 }
9120 }
9121
9122 newval = MAX3(lval, rval, 0.0);
9123 assert(SCIPisSumRelLE(scip, newval, val));
9124
9125 /* Try to avoid cancellation in computation of lhs/rhs */
9126 newlhs = consdata->lhs - val * lb;
9127 newlhs += newval * lb;
9128 newrhs = consdata->rhs - val * ub;
9129 newrhs += newval * ub;
9130
9131 if( !SCIPisSumRelEQ(scip, newval, val) )
9132 {
9133 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9134 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9135 maxactivity, consdata->lhs, consdata->rhs);
9136
9137 /* update the coefficient and the activity bounds */
9138 if( SCIPisZero(scip, newval) )
9139 {
9140 SCIP_CALL( delCoefPos(scip, cons, i) );
9141 --i;
9142 }
9143 else
9144 {
9145 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9146 }
9147 ++(*nchgcoefs);
9148
9149 /* get the new minimal and maximal activity of the constraint */
9150 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9151 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9152
9153 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9154 {
9155 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9156 consdata->lhs, newlhs);
9157
9158 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9159 (*nchgsides)++;
9160 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9161 }
9162
9163 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9164 {
9165 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9166 consdata->rhs, newrhs);
9167
9168 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9169 (*nchgsides)++;
9170 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9171 }
9172 }
9173 }
9174 else
9175 {
9176 if( !SCIPisInfinity(scip, -minleftactivity) )
9177 {
9178 assert(!SCIPisInfinity(scip, val));
9179 assert(!SCIPisInfinity(scip, lb));
9180 if( SCIPisInfinity(scip, -lb) )
9181 minleftactivity = -SCIPinfinity(scip);
9182 else
9183 minleftactivity += val * lb;
9184 }
9185
9186 if( !SCIPisInfinity(scip, maxleftactivity) )
9187 {
9188 assert(!SCIPisInfinity(scip, val));
9189 assert(!SCIPisInfinity(scip, -ub));
9190 if( SCIPisInfinity(scip,ub) )
9191 maxleftactivity = SCIPinfinity(scip);
9192 else
9193 maxleftactivity += val * ub;
9194 }
9195 }
9196 }
9197 else
9198 {
9199 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9200 isvarrelevant[i] = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS
9201 && SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs);
9202
9203 if( isvarrelevant[i] )
9204 {
9205 /* change coefficients:
9206 * ai' := min(rhs - maxact, minact - lhs)
9207 * lhs' := lhs - (ai - ai')*ui
9208 * rhs' := rhs - (ai - ai')*li
9209 */
9210
9211 lval = minactivity - consdata->lhs;
9212 rval = consdata->rhs - maxactivity;
9213
9214 /* Try to avoid cancellation, if there are only two variables */
9215 if( consdata->nvars == 2 )
9216 {
9217 SCIP_Real otherval;
9218 otherval = consdata->vals[1-i];
9219
9220 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9221 {
9222 lval = val*ub - consdata->lhs;
9223 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9224 }
9225
9226 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9227 {
9228 rval = consdata->rhs - val*lb;
9229 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9230 }
9231 }
9232
9233 newval = MIN3(lval, rval, 0.0);
9234 assert(SCIPisSumRelGE(scip, newval, val));
9235
9236 /* Try to avoid cancellation in computation of lhs/rhs */
9237 newlhs = consdata->lhs - val * ub;
9238 newlhs += newval * ub;
9239 newrhs = consdata->rhs - val * lb;
9240 newrhs += newval * lb;
9241
9242 if( !SCIPisSumRelEQ(scip, newval, val) )
9243 {
9244 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9245 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9246 maxactivity, consdata->lhs, consdata->rhs);
9247
9248 /* update the coefficient and the activity bounds */
9249 if( SCIPisZero(scip, newval) )
9250 {
9251 SCIP_CALL( delCoefPos(scip, cons, i) );
9252 --i;
9253 }
9254 else
9255 {
9256 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9257 }
9258 ++(*nchgcoefs);
9259
9260 /* get the new minimal and maximal activity of the constraint */
9261 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9262 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9263
9264 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9265 {
9266 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9267 consdata->lhs, newlhs);
9268
9269 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9270 (*nchgsides)++;
9271 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9272 }
9273
9274 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9275 {
9276 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9277 consdata->rhs, newrhs);
9278
9279 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9280 (*nchgsides)++;
9281 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9282 }
9283 }
9284 }
9285 else
9286 {
9287 if( !SCIPisInfinity(scip, -minleftactivity) )
9288 {
9289 assert(!SCIPisInfinity(scip, -val));
9290 assert(!SCIPisInfinity(scip, -ub));
9291 if( SCIPisInfinity(scip, ub) )
9292 minleftactivity = -SCIPinfinity(scip);
9293 else
9294 minleftactivity += val * ub;
9295 }
9296
9297 if( !SCIPisInfinity(scip, maxleftactivity) )
9298 {
9299 assert(!SCIPisInfinity(scip, -val));
9300 assert(!SCIPisInfinity(scip, lb));
9301 if( SCIPisInfinity(scip, -lb) )
9302 maxleftactivity = SCIPinfinity(scip);
9303 else
9304 maxleftactivity += val * lb;
9305 }
9306 }
9307 }
9308
9309 ++i;
9310 }
9311
9312 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9313 minleftactivity, consdata->rhs);
9314 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9315 maxleftactivity, consdata->lhs);
9316
9317 /* minleft == \infty ==> minactivity == \infty */
9318 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9319 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9320
9321 /* if the lhs is finite, we will check in the following whether the not relevant variables can make lhs feasible;
9322 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9323 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9324 * (<= the exact minactivity), and we might falsely remove coefficients in the following
9325 */
9326 assert(!SCIPisInfinity(scip, minactivity));
9327 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
9328 goto TERMINATE;
9329
9330 /* if the rhs is finite, we will check in the following whether the not relevant variables can make rhs feasible;
9331 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9332 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9333 * (>= the exact maxactivity), and we might falsely remove coefficients in the following
9334 */
9335 assert(!SCIPisInfinity(scip, -maxactivity));
9336 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
9337 goto TERMINATE;
9338
9339 /* correct lhs and rhs by min/max activity of relevant variables
9340 * relevant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9341 */
9342 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9343 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9344
9345 /* check if the constraint contains variables whose coefficient can be removed. The reasoning is the following:
9346 * Each relevant variable can make the lhs/rhs feasible with a deviation of only one in the bound. If _all_ not
9347 * relevant variables together cannot make lhs/rhs redundant, they can be removed from the constraint. aggrrhs may
9348 * contain some near-infinity value, but only if rhs is infinity.
9349 */
9350 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9351 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9352 {
9353 SCIP_Real minleftactivitypart;
9354 SCIP_Real maxleftactivitypart;
9355
9356 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9357
9358 /* remove redundant variables from constraint */
9359 i = 0;
9360 while( i < consdata->nvars )
9361 {
9362 /* consider redundant variable */
9363 if( !isvarrelevant[i] )
9364 {
9365 /* get coefficient and variable's bounds */
9366 var = consdata->vars[i];
9367 val = consdata->vals[i];
9368 assert(!SCIPisZero(scip, val));
9369 lb = SCIPvarGetLbLocal(var);
9370 ub = SCIPvarGetUbLocal(var);
9371
9372 SCIPdebugMsg(scip, "val = %g\tlhs = %g\trhs = %g\n", val, consdata->lhs, consdata->rhs);
9373 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> from constraint since it is redundant\n",
9374 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
9375
9376 /* check sign of coefficient */
9377 if( val >= 0.0 )
9378 {
9379 minleftactivitypart = val * lb;
9380 maxleftactivitypart = val * ub;
9381 }
9382 else
9383 {
9384 minleftactivitypart = val * ub;
9385 maxleftactivitypart = val * lb;
9386 }
9387
9388 /* remove redundant variable */
9389 isvarrelevant[i] = isvarrelevant[consdata->nvars - 1];
9390 SCIP_CALL( delCoefPos(scip, cons, i) );
9391 --i;
9392
9393 /* adjust lhs and right hand side */
9394 newlhs = consdata->lhs - minleftactivitypart;
9395 newrhs = consdata->rhs - maxleftactivitypart;
9396
9397 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9398 {
9399 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9400 consdata->lhs, newlhs);
9401
9402 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9403 ++(*nchgsides);
9404 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9405 }
9406
9407 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9408 {
9409 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9410 consdata->rhs, newrhs);
9411
9412 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9413 ++(*nchgsides);
9414 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9415 }
9416 }
9417
9418 ++i;
9419 }
9420 }
9421
9422TERMINATE:
9423 /* free relevance flags */
9424 SCIPfreeBufferArray(scip, &isvarrelevant);
9425
9426 return SCIP_OKAY;
9427}
9428
9429/** processes equality with only one variable by fixing the variable and deleting the constraint */
9430static
9432 SCIP* scip, /**< SCIP data structure */
9433 SCIP_CONS* cons, /**< linear constraint */
9434 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9435 int* nfixedvars, /**< pointer to count number of fixed variables */
9436 int* ndelconss /**< pointer to count number of deleted constraints */
9437 )
9438{
9439 SCIP_CONSDATA* consdata;
9440 SCIP_VAR* var;
9441 SCIP_Real val;
9442 SCIP_Real fixval;
9443 SCIP_Bool infeasible;
9444 SCIP_Bool fixed;
9445
9446 assert(scip != NULL);
9447 assert(cons != NULL);
9448 assert(cutoff != NULL);
9449 assert(nfixedvars != NULL);
9450 assert(ndelconss != NULL);
9451
9452 consdata = SCIPconsGetData(cons);
9453 assert(consdata != NULL);
9454 assert(consdata->nvars == 1);
9455 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9456
9457 /* calculate the value to fix the variable to */
9458 var = consdata->vars[0];
9459 val = consdata->vals[0];
9460 assert(!SCIPisZero(scip, val));
9461 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9462 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9463 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9464 SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9465
9466 /* fix variable */
9467 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9468 if( infeasible )
9469 {
9470 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9471 *cutoff = TRUE;
9472 return SCIP_OKAY;
9473 }
9474 if( fixed )
9475 (*nfixedvars)++;
9476
9477 /* disable constraint */
9478 SCIP_CALL( SCIPdelCons(scip, cons) );
9479 if( !consdata->upgraded )
9480 (*ndelconss)++;
9481
9482 return SCIP_OKAY;
9483}
9484
9485/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9486static
9488 SCIP* scip, /**< SCIP data structure */
9489 SCIP_CONS* cons, /**< linear constraint */
9490 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9491 int* naggrvars, /**< pointer to count number of aggregated variables */
9492 int* ndelconss /**< pointer to count number of deleted constraints */
9493 )
9494{
9495 SCIP_CONSDATA* consdata;
9496 SCIP_Bool infeasible;
9497 SCIP_Bool redundant;
9498 SCIP_Bool aggregated;
9499
9500 assert(scip != NULL);
9501 assert(cons != NULL);
9502 assert(cutoff != NULL);
9503 assert(naggrvars != NULL);
9504 assert(ndelconss != NULL);
9505
9506 consdata = SCIPconsGetData(cons);
9507 assert(consdata != NULL);
9508 assert(consdata->nvars == 2);
9509 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9510
9511 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9512 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9513 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9514
9515 /* aggregate the equality */
9516 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9517 consdata->rhs, &infeasible, &redundant, &aggregated) );
9518
9519 /* check for infeasibility of aggregation */
9520 if( infeasible )
9521 {
9522 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9523 *cutoff = TRUE;
9524 return SCIP_OKAY;
9525 }
9526
9527 /* count the aggregation */
9528 if( aggregated )
9529 (*naggrvars)++;
9530
9531 /* delete the constraint, if it is redundant */
9532 if( redundant )
9533 {
9534 SCIP_CALL( SCIPdelCons(scip, cons) );
9535
9536 if( !consdata->upgraded )
9537 (*ndelconss)++;
9538 }
9539
9540 return SCIP_OKAY;
9541}
9542
9543/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9544static
9546 SCIP* scip, /**< SCIP data structure */
9547 SCIP_CONSDATA* consdata, /**< linear constraint data */
9548 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9549 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9550 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9551 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9552 )
9553{
9554 SCIP_Real slackvarlb;
9555 SCIP_Real slackvarub;
9556
9557 assert(scip != NULL);
9558 assert(consdata != NULL);
9559 assert(newlhs != NULL);
9560 assert(newrhs != NULL);
9561 assert(!SCIPisInfinity(scip, -consdata->lhs));
9562 assert(!SCIPisInfinity(scip, consdata->rhs));
9563
9564 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9565 slackvarub = SCIPvarGetUbGlobal(slackvar);
9566 if( slackcoef > 0.0 )
9567 {
9568 if( SCIPisInfinity(scip, -slackvarlb) )
9569 *newrhs = SCIPinfinity(scip);
9570 else
9571 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9572 if( SCIPisInfinity(scip, slackvarub) )
9573 *newlhs = -SCIPinfinity(scip);
9574 else
9575 *newlhs = consdata->lhs - slackcoef * slackvarub;
9576 }
9577 else
9578 {
9579 if( SCIPisInfinity(scip, -slackvarlb) )
9580 *newlhs = -SCIPinfinity(scip);
9581 else
9582 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9583 if( SCIPisInfinity(scip, slackvarub) )
9584 *newrhs = SCIPinfinity(scip);
9585 else
9586 *newrhs = consdata->lhs - slackcoef * slackvarub;
9587 }
9588 assert(SCIPisLE(scip, *newlhs, *newrhs));
9589}
9590
9591/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9592 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9593 * is implicitly integral by this constraint
9594 *
9595 * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9596 * can help.
9597 */
9598static
9600 SCIP* scip, /**< SCIP data structure */
9601 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9602 SCIP_CONS* cons, /**< linear constraint */
9603 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9604 int* naggrvars, /**< pointer to count number of aggregated variables */
9605 int* ndelconss, /**< pointer to count number of deleted constraints */
9606 int* nchgvartypes /**< pointer to count number of changed variable types */
9607 )
9608{
9609 SCIP_CONSDATA* consdata;
9610 SCIP_VAR** vars;
9611 SCIP_Real* vals;
9612 SCIP_VARTYPE bestslacktype;
9613 SCIP_VARTYPE slacktype;
9614 SCIP_Real lhs;
9615 SCIP_Real rhs;
9616 SCIP_Real bestslackdomrng;
9617 SCIP_Real minabsval;
9618 SCIP_Real maxabsval;
9619 SCIP_Bool bestremovescons;
9620 SCIP_Bool coefszeroone;
9621 SCIP_Bool coefsintegral;
9622 SCIP_Bool varsintegral;
9623 SCIP_Bool infeasible;
9624 SCIP_Bool samevar;
9625 int supinf; /* counter for infinite contributions to the supremum of a possible
9626 * multi-aggregation
9627 */
9628 int infinf; /* counter for infinite contributions to the infimum of a possible
9629 * multi-aggregation
9630 */
9631 int maxnlocksstay;
9632 int maxnlocksremove;
9633 int bestslackpos;
9634 int bestnlocks;
9635 int ncontvars;
9636 int contvarpos;
9637 int nintvars;
9638 int nimplvars;
9639 int intvarpos;
9640 int v;
9641
9642 assert(scip != NULL);
9643 assert(cons != NULL);
9644 assert(cutoff != NULL);
9645 assert(naggrvars != NULL);
9646
9647 consdata = SCIPconsGetData(cons);
9648 assert(consdata != NULL);
9649 assert(consdata->nvars > 2);
9650 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9651
9652 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9653
9654 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9655 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9656 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9657 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9658 */
9659 lhs = consdata->lhs;
9660 rhs = consdata->rhs;
9661 maxnlocksstay = 0;
9662 if( consdata->nvars == 3 )
9663 {
9664 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9665 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9666 */
9667 maxnlocksremove = 3;
9668 }
9669 else if( consdata->nvars == 4 )
9670 {
9671 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9672 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9673 */
9674 maxnlocksremove = 2;
9675 }
9676 else
9677 {
9678 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9679 maxnlocksremove = 1;
9680 }
9681
9682 /* the locks on this constraint can be ignored */
9683 if( SCIPconsIsChecked(cons) )
9684 {
9685 if( !SCIPisInfinity(scip, -lhs) )
9686 {
9687 maxnlocksstay++;
9688 maxnlocksremove++;
9689 }
9690 if( !SCIPisInfinity(scip, rhs) )
9691 {
9692 maxnlocksstay++;
9693 maxnlocksremove++;
9694 }
9695 }
9696
9697 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9698 vars = consdata->vars;
9699 vals = consdata->vals;
9700 bestslackpos = -1;
9701 bestslacktype = SCIP_VARTYPE_BINARY;
9702 bestnlocks = INT_MAX;
9703 bestremovescons = FALSE;
9704 bestslackdomrng = 0.0;
9705 coefszeroone = TRUE;
9706 coefsintegral = TRUE;
9707 varsintegral = TRUE;
9708 ncontvars = 0;
9709 contvarpos = -1;
9710 nintvars = 0;
9711 nimplvars = 0;
9712 intvarpos = -1;
9713 minabsval = SCIPinfinity(scip);
9714 maxabsval = -1.0;
9715 for( v = 0; v < consdata->nvars; ++v )
9716 {
9717 SCIP_VAR* var;
9718 SCIP_Real val;
9719 SCIP_Real absval;
9720 SCIP_Real varlb;
9721 SCIP_Real varub;
9722 SCIP_Bool iscont;
9723 int nlocks;
9724
9725 assert(vars != NULL);
9726 assert(vals != NULL);
9727
9728 var = vars[v];
9729 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9731 varlb = SCIPvarGetLbGlobal(var);
9732 varub = SCIPvarGetUbGlobal(var);
9733
9734 val = vals[v];
9735 absval = REALABS(val);
9736 assert(SCIPisPositive(scip, absval));
9737
9738 /* calculate minimal and maximal absolute value */
9739 if( absval < minabsval )
9740 minabsval = absval;
9741 if( absval > maxabsval )
9742 maxabsval = absval;
9743
9744 /*TODO: why exit here when implied integrality can still be derived?!*/
9745 /* do not try to multi aggregate, when numerical bad */
9746 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9747 return SCIP_OKAY;
9748
9749 slacktype = SCIPvarGetType(var);
9750 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9751 coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9752 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9753 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9754
9755 /* update candidates for continuous -> implint and integer -> implint conversion */
9756 if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9757 {
9758 ncontvars++;
9759 contvarpos = v;
9760 }
9761 else if( slacktype == SCIP_VARTYPE_IMPLINT )
9762 {
9763 ++nimplvars;
9764 }
9765 else if( slacktype == SCIP_VARTYPE_INTEGER )
9766 {
9767 nintvars++;
9768 intvarpos = v;
9769 }
9770
9771 /* check, if variable is already fixed or aggregated */
9772 if( !SCIPvarIsActive(var) )
9773 continue;
9774
9775 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9777
9778 if( nlocks > maxnlocksremove )
9779 continue;
9780
9781 /* check, if variable can be used as a slack variable */
9782 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9783 !SCIPdoNotMultaggrVar(scip, var) )
9784 {
9785 SCIP_Bool better;
9786 SCIP_Bool equal;
9787 SCIP_Real slackdomrng;
9788
9789 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9790 slackdomrng = SCIPinfinity(scip);
9791 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9792 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9793 return SCIP_OKAY;
9794 else
9795 {
9796 slackdomrng = (varub - varlb)*absval;
9797 assert(!SCIPisInfinity(scip, slackdomrng));
9798 }
9799 equal = FALSE;
9800 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9801 if( !better && slacktype == bestslacktype )
9802 {
9803 better = (nlocks < bestnlocks);
9804 if( nlocks == bestnlocks && !bestremovescons )
9805 {
9806 better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9807 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9808 }
9809 }
9810
9811 if( better || equal )
9812 {
9813 SCIP_Real minresactivity;
9814 SCIP_Real maxresactivity;
9815 SCIP_Real newlhs;
9816 SCIP_Real newrhs;
9817 SCIP_Bool removescons;
9818 SCIP_Bool ismintight;
9819 SCIP_Bool ismaxtight;
9820 SCIP_Bool isminsettoinfinity;
9821 SCIP_Bool ismaxsettoinfinity;
9822
9823 /* check if the constraint becomes redundant after multi-aggregation */
9824 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9825 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
9826
9827 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9828 * activity
9829 */
9830 if( !ismintight || !ismaxtight )
9831 continue;
9832
9833 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9834 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9835
9836 /* check resactivities for reliability */
9837 if( removescons )
9838 {
9839 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9840 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9841
9842 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9843 && SCIPisFeasLE(scip, newlhs, minresactivity))
9844 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9845
9846 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9847 }
9848
9849 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9850 if( conshdlrdata->multaggrremove && !removescons )
9851 continue;
9852
9853 /* prefer variables that make the constraints redundant */
9854 if( bestremovescons && !removescons )
9855 continue;
9856
9857 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9858 * other constraints
9859 */
9860 if( !removescons && nlocks > maxnlocksstay )
9861 continue;
9862
9863 better = better || (!bestremovescons && removescons);
9864 if( better )
9865 {
9866 bestslackpos = v;
9867 bestslacktype = slacktype;
9868 bestnlocks = nlocks;
9869 bestslackdomrng = slackdomrng;
9870 bestremovescons = removescons;
9871 }
9872 }
9873 }
9874 }
9875
9876 /* if all coefficients and variables are integral, the right hand side must also be integral */
9877 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9878 {
9879 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9881 *cutoff = TRUE;
9882 return SCIP_OKAY;
9883 }
9884
9885 supinf = 0;
9886 infinf = 0;
9887 samevar = FALSE;
9888
9889 /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9890 for( v = 0; v < consdata->nvars; ++v )
9891 {
9892 if( v != bestslackpos )
9893 {
9894 if( SCIPisPositive(scip, consdata->vals[v]) )
9895 {
9896 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9897 {
9898 ++supinf;
9899 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9900 {
9901 ++infinf;
9902 samevar = TRUE;
9903 }
9904 }
9905 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9906 ++infinf;
9907 }
9908 else if( SCIPisNegative(scip, consdata->vals[v]) )
9909 {
9910 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9911 {
9912 ++supinf;
9913 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9914 {
9915 ++infinf;
9916 samevar = TRUE;
9917 }
9918 }
9919 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9920 ++infinf;
9921 }
9922 }
9923 }
9924 assert(!samevar || (supinf > 0 && infinf > 0));
9925
9926 /*TODO: implint detection again terminates early here*/
9927 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9928 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9929 if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9930 {
9931 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9932 return SCIP_OKAY;
9933 }
9934
9935 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9936 * we cannot aggregate the variable, because the integrality condition would get lost
9937 * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9938 * loose the integrality condition for this variable.
9939 */
9940 if( bestslackpos >= 0
9941 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9942 || (coefsintegral && varsintegral && nimplvars == 0)) )
9943 {
9944 SCIP_VAR* slackvar;
9946 SCIP_Real slackcoef;
9947 SCIP_Real aggrconst;
9948 SCIP_Real newlhs;
9949 SCIP_Real newrhs;
9950 SCIP_Bool aggregated;
9951
9952 /* we found a slack variable that only occurs in at most one other constraint:
9953 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9954 */
9955 assert(bestslackpos < consdata->nvars);
9956
9957 /* do not multi aggregate binary variables */
9958 if( SCIPvarIsBinary(vars[bestslackpos]) )
9959 return SCIP_OKAY;
9960
9961 /* convert equality into inequality by deleting the slack variable:
9962 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9963 */
9964 slackvar = vars[bestslackpos];
9965 slackcoef = vals[bestslackpos];
9966 assert(!SCIPisZero(scip, slackcoef));
9967 aggrconst = consdata->rhs/slackcoef;
9968
9969 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9970 assert(SCIPisLE(scip, newlhs, newrhs));
9971 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9972 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9973 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9974
9975 /* allocate temporary memory */
9976 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
9977
9978 /* set up the multi-aggregation */
9979 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9980 for( v = 0; v < consdata->nvars; ++v )
9981 {
9982 scalars[v] = -consdata->vals[v]/slackcoef;
9983 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
9984 }
9985 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9986 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9987 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9988
9989 /* perform the multi-aggregation */
9990 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
9991 &infeasible, &aggregated) );
9992 assert(aggregated);
9993
9994 /* free temporary memory */
9996
9997 /* check for infeasible aggregation */
9998 if( infeasible )
9999 {
10000 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10001 *cutoff = TRUE;
10002 return SCIP_OKAY;
10003 }
10004
10005 (*naggrvars)++;
10006
10007 /* delete the constraint if it became redundant */
10008 if( bestremovescons )
10009 {
10010 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10011 SCIP_CALL( SCIPdelCons(scip, cons) );
10012
10013 if( !consdata->upgraded )
10014 (*ndelconss)++;
10015 }
10016 }
10017 else if( ncontvars == 1 )
10018 {
10019 SCIP_VAR* var;
10020
10021 assert(0 <= contvarpos && contvarpos < consdata->nvars);
10022 var = vars[contvarpos];
10024
10025 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10026 {
10027 /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10028 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10029 {
10030 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10031 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10032 SCIPconsGetName(cons), SCIPvarGetName(var));
10033 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10034 (*nchgvartypes)++;
10035 if( infeasible )
10036 {
10037 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10038 *cutoff = TRUE;
10039
10040 return SCIP_OKAY;
10041 }
10042 }
10043 /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10044 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10045 else if( !SCIPdoNotAggr(scip) )
10046 {
10047 SCIP_VAR* newvar;
10048 SCIP_Real absval;
10049 char newvarname[SCIP_MAXSTRLEN];
10050 SCIP_Bool redundant;
10051 SCIP_Bool aggregated;
10052
10053 absval = REALABS(vals[contvarpos]);
10054
10055 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10056
10057 /* create new implicit variable for aggregation */
10058 SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10060
10061 /* add new variable to problem */
10062 SCIP_CALL( SCIPaddVar(scip, newvar) );
10063
10064#ifdef WITH_DEBUG_SOLUTION
10065 if( SCIPdebugIsMainscip(scip) )
10066 {
10067 SCIP_Real varval;
10068 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10069 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10070 }
10071#endif
10072
10073 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10074 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10075 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10076
10077 /* aggregate continuous and implicit variable */
10078 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10079
10080 if( infeasible )
10081 {
10082 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10083 SCIPvarGetName(var), SCIPvarGetName(newvar));
10084 *cutoff = TRUE;
10085
10086 /* release implicit variable */
10087 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10088
10089 return SCIP_OKAY;
10090 }
10091
10092 /* release implicit variable */
10093 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10094
10095 if( aggregated )
10096 (*naggrvars)++;
10097 else
10098 return SCIP_OKAY;
10099 }
10100
10101 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10102 * again
10103 */
10104 consdata->boundstightened = 0;
10105 consdata->rangedrowpropagated = 0;
10106 consdata->presolved = FALSE;
10107 }
10108 }
10109 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10110 {
10111 SCIP_VAR* var;
10112
10113 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10114 * -> we don't convert integers into implints if the row is a 0/1-row
10115 */
10116 assert(varsintegral);
10117 assert(0 <= intvarpos && intvarpos < consdata->nvars);
10118 var = vars[intvarpos];
10119 assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10120
10121 if( coefsintegral
10122 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10123 && SCIPisFeasIntegral(scip, consdata->rhs) )
10124 {
10125 /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10126 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10127 SCIPconsGetName(cons), SCIPvarGetName(var));
10128 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10129 (*nchgvartypes)++;
10130 if( infeasible )
10131 {
10132 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10133 *cutoff = TRUE;
10134
10135 return SCIP_OKAY;
10136 }
10137 }
10138 }
10139
10140 return SCIP_OKAY;
10141}
10142
10143/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10144static
10146 SCIP* scip, /**< SCIP data structure */
10147 SCIP_CONSDATA* consdata, /**< linear constraint data */
10148 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10149 * objective function */
10150 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10151 * this constraint */
10152 )
10153{
10154 SCIP_VAR** vars;
10155 SCIP_VAR* var;
10156 SCIP_Real objval;
10157 SCIP_Bool negated;
10158 int nvars;
10159 int v;
10160
10161 vars = consdata->vars;
10162 nvars = consdata->nvars;
10163
10164 assert(vars != NULL);
10165
10166 for( v = 0; v < nvars; ++v )
10167 {
10168 negated = FALSE;
10169 var = vars[v];
10170 assert(var != NULL);
10171
10172 if( SCIPvarIsNegated(var) )
10173 {
10174 negated = TRUE;
10175 var = SCIPvarGetNegatedVar(var);
10176 assert(var != NULL);
10177 }
10178
10179 objval = SCIPvarGetObj(var);
10180
10181 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10182 * function
10183 */
10184 if( SCIPisZero(scip, objval) )
10185 return FALSE;
10186 else
10187 {
10188 SCIP_Real val;
10189
10190 val = consdata->vals[v];
10191
10192 if( negated )
10193 {
10194 if( v == 0 )
10195 {
10196 /* the first variable defines the scale */
10197 (*scale) = val / -objval;
10198
10199 (*offset) += val;
10200 }
10201 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10202 (*offset) += val;
10203 else
10204 return FALSE;
10205 }
10206 else if( v == 0 )
10207 {
10208 /* the first variable defines the scale */
10209 (*scale) = val / objval;
10210 }
10211 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10212 return FALSE;
10213 }
10214 }
10215
10216 return TRUE;
10217}
10218
10219/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10220 * objective coefficients and add an objective offset
10221 */
10222static
10224 SCIP* scip, /**< SCIP data structure */
10225 SCIP_CONS* cons, /**< linear equation constraint */
10226 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10227 )
10228{
10229 SCIP_CONSDATA* consdata;
10230 SCIP_Real offset;
10231 SCIP_Real scale;
10232 SCIP_Bool applicable;
10233 int nobjvars;
10234 int nvars;
10235 int v;
10236
10237 assert(scip != NULL);
10238 assert(cons != NULL);
10239 assert(conshdlrdata != NULL);
10240
10241 consdata = SCIPconsGetData(cons);
10242 assert(consdata != NULL);
10243 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10244
10245 nvars = consdata->nvars;
10246 nobjvars = SCIPgetNObjVars(scip);
10247
10248 /* check if the linear equality constraints does not have more variables than the objective function */
10249 if( nvars > nobjvars || nvars == 0 )
10250 return SCIP_OKAY;
10251
10252 /* check for allowance of algorithm */
10253 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10254 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10255 return SCIP_OKAY;
10256
10257 offset = consdata->rhs;
10258 scale = 1.0;
10259
10260 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10261 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10262
10263 if( applicable )
10264 {
10265 SCIP_VAR** vars;
10266
10267 vars = consdata->vars;
10268 assert(vars != NULL);
10269
10270 offset /= scale;
10271
10272 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10273 SCIPconsGetName(cons), consdata->rhs, offset);
10274
10275 /* make equality a model constraint to ensure optimality in this direction */
10278
10279 /* set all objective coefficient to zero */
10280 for( v = 0; v < nvars; ++v )
10281 {
10282 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10283 }
10284
10285 /* add an objective offset */
10286 SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10287 }
10288
10289 return SCIP_OKAY;
10290}
10291
10292/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10293static
10295 SCIP* scip, /**< SCIP data structure */
10296 SCIP_CONS* cons, /**< constraint */
10297 SCIP_Real primalbound /**< feasible primal bound */
10298 )
10299{
10300 SCIP_Real cutoffbound;
10301
10302 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10303 * accepted
10304 */
10305 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10306
10307 if( cutoffbound < SCIPgetCutoffbound(scip) )
10308 {
10309 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10310
10311 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10312 }
10313 else
10314 {
10315 SCIP_CONSDATA* consdata;
10316
10317 consdata = SCIPconsGetData(cons);
10318 assert(consdata != NULL);
10319
10320 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10321 * resulted from one side
10322 */
10323 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10324 {
10325 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10326 * propagation
10327 */
10330 }
10331 }
10332
10333 return SCIP_OKAY;
10334}
10335
10336/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10337 * constraint enters the LP by setting the initial and separated flag to FALSE
10338 */
10339static
10341 SCIP* scip, /**< SCIP data structure */
10342 SCIP_CONS* cons, /**< linear constraint */
10343 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10344 )
10345{
10346 SCIP_CONSDATA* consdata;
10347 SCIP_Real offset;
10348 SCIP_Real scale;
10349 SCIP_Bool applicable;
10350 int nobjvars;
10351 int nvars;
10352
10353 assert(scip != NULL);
10354 assert(cons != NULL);
10355 assert(conshdlrdata != NULL);
10356
10357 consdata = SCIPconsGetData(cons);
10358 assert(consdata != NULL);
10359
10360 /* ignore equalities since these are covered by the method checkPartialObjective() */
10361 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10362 return SCIP_OKAY;
10363
10364 nvars = consdata->nvars;
10365 nobjvars = SCIPgetNObjVars(scip);
10366
10367 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10368 * initial and/or separated flag is set to FALSE
10369 */
10370 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10371 return SCIP_OKAY;
10372
10373 offset = 0.0;
10374 scale = 1.0;
10375
10376 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10377 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10378 */
10379 if( nobjvars == 0 )
10380 return SCIP_OKAY;
10381
10382 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10383 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10384
10385 if( applicable )
10386 {
10387 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10388 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10389
10390 assert(scale != 0.0);
10391
10392 if( scale > 0.0 )
10393 {
10394 if( conshdlrdata->detectcutoffbound && rhsfinite )
10395 {
10396 SCIP_Real primalbound;
10397
10398 primalbound = (consdata->rhs - offset) / scale;
10399
10400 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10401 SCIPconsGetName(cons), primalbound);
10402
10403 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10404 }
10405
10406 if( conshdlrdata->detectlowerbound && lhsfinite )
10407 {
10408 SCIP_Real lowerbound;
10409
10410 lowerbound = (consdata->lhs - offset) / scale;
10411
10412 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10413 SCIPconsGetName(cons), lowerbound);
10414
10416 }
10417
10418 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10419 (conshdlrdata->detectlowerbound && !rhsfinite) )
10420 {
10421 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10424 }
10425 }
10426 else
10427 {
10428 if( conshdlrdata->detectlowerbound && rhsfinite )
10429 {
10430 SCIP_Real lowerbound;
10431
10432 lowerbound = (consdata->rhs - offset) / scale;
10433
10434 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10435 SCIPconsGetName(cons), lowerbound);
10436
10438 }
10439
10440 if( conshdlrdata->detectcutoffbound && lhsfinite )
10441 {
10442 SCIP_Real primalbound;
10443
10444 primalbound = (consdata->lhs - offset) / scale;
10445
10446 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10447 SCIPconsGetName(cons), primalbound);
10448
10449 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10450 }
10451
10452 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10453 (conshdlrdata->detectlowerbound && !lhsfinite) )
10454 {
10455 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10458 }
10459 }
10460 }
10461
10462 return SCIP_OKAY;
10463}
10464
10465/** converts special equalities */
10466static
10468 SCIP* scip, /**< SCIP data structure */
10469 SCIP_CONS* cons, /**< linear constraint */
10470 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10471 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10472 int* nfixedvars, /**< pointer to count number of fixed variables */
10473 int* naggrvars, /**< pointer to count number of aggregated variables */
10474 int* ndelconss, /**< pointer to count number of deleted constraints */
10475 int* nchgvartypes /**< pointer to count number of changed variable types */
10476 )
10477{
10478 SCIP_CONSDATA* consdata;
10479
10480 assert(scip != NULL);
10481 assert(cons != NULL);
10482 assert(conshdlrdata != NULL);
10483 assert(cutoff != NULL);
10484 assert(nfixedvars != NULL);
10485 assert(naggrvars != NULL);
10486 assert(ndelconss != NULL);
10487
10488 consdata = SCIPconsGetData(cons);
10489 assert(consdata != NULL);
10490 assert(consdata->removedfixings);
10491
10492 /* do nothing on inequalities */
10493 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10494 return SCIP_OKAY;
10495
10496 /* depending on the number of variables, call a special conversion method */
10497 if( consdata->nvars == 1 )
10498 {
10499 /* fix variable */
10500 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10501 }
10502 else if( consdata->nvars == 2 )
10503 {
10504 /* aggregate one of the variables */
10505 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10506 }
10507 else
10508 {
10509 /* check if the equality is part of the objective function */
10510 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10511
10512 /* try to multi-aggregate one of the variables */
10513 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss, nchgvartypes) );
10514 }
10515
10516 return SCIP_OKAY;
10517}
10518
10519/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10520 * integral
10521 */
10522static
10524 SCIP* scip, /**< SCIP data structure */
10525 SCIP_CONSDATA* consdata, /**< linear constraint */
10526 int pos, /**< position of variable to be left out */
10527 SCIP_Real val /**< value to divide the coefficients by */
10528 )
10529{
10530 int v;
10531
10532 assert(scip != NULL);
10533 assert(consdata != NULL);
10534 assert(0 <= pos && pos < consdata->nvars);
10535
10536 for( v = 0; v < consdata->nvars; ++v )
10537 {
10538 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10539 return FALSE;
10540 }
10541
10542 return TRUE;
10543}
10544
10545/** 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$,
10546 * 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$
10547 */
10548static
10550 SCIP* scip, /**< SCIP data structure */
10551 SCIP_Real side, /**< lhs or rhs */
10552 SCIP_Real val, /**< coefficient */
10553 SCIP_Real minresactivity, /**< minimal residual activity */
10554 SCIP_Real maxresactivity, /**< maximal residual activity */
10555 SCIP_Real* minval, /**< pointer to store calculated minval */
10556 SCIP_Real* maxval /**< pointer to store calculated maxval */
10557 )
10558{
10559 assert(scip != NULL);
10560 assert(minval != NULL);
10561 assert(maxval != NULL);
10562
10563 if( val > 0.0 )
10564 {
10565 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10566 *minval = -maxresactivity;
10567 else
10568 *minval = (side - maxresactivity)/val;
10569
10570 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10571 *maxval = -minresactivity;
10572 else
10573 *maxval = (side - minresactivity)/val;
10574 }
10575 else
10576 {
10577 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10578 *minval = minresactivity;
10579 else
10580 *minval = (side - minresactivity)/val;
10581
10582 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10583 *maxval = maxresactivity;
10584 else
10585 *maxval = (side - maxresactivity)/val;
10586 }
10587}
10588
10589
10590/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10591 * linear inequality
10592 */
10593static
10595 SCIP* scip, /**< SCIP data structure */
10596 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10597 SCIP_CONS* cons, /**< linear constraint */
10598 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10599 int* nfixedvars, /**< pointer to count number of fixed variables */
10600 int* naggrvars, /**< pointer to count number of aggregated variables */
10601 int* ndelconss, /**< pointer to count number of deleted constraints */
10602 int* nchgvartypes /**< pointer to count number of changed variable types */
10603 )
10604{
10605 SCIP_CONSDATA* consdata;
10606 SCIP_Bool lhsexists;
10607 SCIP_Bool rhsexists;
10608 SCIP_Bool bestisint;
10609 SCIP_Bool bestislhs;
10610 SCIP_Real minabsval;
10611 SCIP_Real maxabsval;
10612 int bestpos;
10613 int i;
10614 int maxotherlocks;
10615
10616 assert(scip != NULL);
10617 assert(cons != NULL);
10618 assert(cutoff != NULL);
10619 assert(nfixedvars != NULL);
10620 assert(naggrvars != NULL);
10621 assert(ndelconss != NULL);
10622
10623 /* only process checked constraints (for which the locks are increased);
10624 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10625 * dualfix presolver
10626 */
10627 if( !SCIPconsIsChecked(cons) )
10628 return SCIP_OKAY;
10629
10630 consdata = SCIPconsGetData(cons);
10631 assert(consdata != NULL);
10632
10633 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10634 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10635
10636 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10637 * can use it safely for aggregation and break the search loop
10638 */
10639 bestpos = -1;
10640 bestisint = TRUE;
10641 bestislhs = FALSE;
10642
10643 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10644 * everything else would produce fill-in. Exceptions:
10645 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10646 * produced.
10647 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10648 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10649 * six nonzeros (two variables per substitution).
10650 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10651 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10652 * six nonzeros (three variables per substitution). God exists!
10653 */
10654 if( consdata->nvars <= 2 )
10655 maxotherlocks = INT_MAX;
10656 else if( consdata->nvars == 3 )
10657 maxotherlocks = 3;
10658 else if( consdata->nvars == 4 )
10659 maxotherlocks = 2;
10660 else
10661 maxotherlocks = 1;
10662
10663 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10664 if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10665 maxotherlocks++;
10666
10667 minabsval = SCIPinfinity(scip);
10668 maxabsval = -1.0;
10669 for( i = 0; i < consdata->nvars && bestisint; ++i )
10670 {
10671 SCIP_VAR* var;
10672 SCIP_Bool isint;
10673 SCIP_Real val;
10674 SCIP_Real absval;
10675 SCIP_Real obj;
10676 SCIP_Real lb;
10677 SCIP_Real ub;
10678 SCIP_Bool agglhs;
10679 SCIP_Bool aggrhs;
10680
10681 val = consdata->vals[i];
10682 absval = REALABS(val);
10683
10684 /* calculate minimal and maximal absolute value */
10685 if( absval < minabsval )
10686 minabsval = absval;
10687 if( absval > maxabsval )
10688 maxabsval = absval;
10689
10690 /* do not try to multi aggregate, when numerical bad */
10691 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10692 return SCIP_OKAY;
10693
10694 var = consdata->vars[i];
10696
10697 /* if we already found a candidate, skip integers */
10698 if( bestpos >= 0 && isint )
10699 continue;
10700
10701 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10702 * active, fixed, or single-aggregated with another binary variable
10703 */
10704 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10705 continue;
10706
10707 if ( SCIPdoNotMultaggrVar(scip, var) )
10708 continue;
10709
10710 val = consdata->vals[i];
10711 obj = SCIPvarGetObj(var);
10712 lb = SCIPvarGetLbGlobal(var);
10713 ub = SCIPvarGetUbGlobal(var);
10714
10715 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10716 *
10717 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10718 * - constraint is the only one that forbids fixing the variable to its lower bound
10719 * - 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
10720 *
10721 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10722 * - constraint is the only one that forbids fixing the variable to its upper bound
10723 * - 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
10724 *
10725 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10726 * - constraint is the only one that forbids fixing the variable to its upper bound
10727 * - 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
10728 *
10729 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10730 * - constraint is the only one that forbids fixing the variable to its lower bound
10731 * - 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
10732 *
10733 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10734 * of all x_j
10735 * furthermore: we only want to apply this, if no fill-in will be produced
10736 */
10737 agglhs = lhsexists
10738 && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10739 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10740 || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10741 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10742 aggrhs = rhsexists
10743 && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10744 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10745 || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10746 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10747 if( agglhs || aggrhs )
10748 {
10749 SCIP_Real minresactivity;
10750 SCIP_Real maxresactivity;
10751 SCIP_Real minval;
10752 SCIP_Real maxval;
10753 SCIP_Bool ismintight;
10754 SCIP_Bool ismaxtight;
10755 SCIP_Bool isminsettoinfinity;
10756 SCIP_Bool ismaxsettoinfinity;
10757
10758 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10759 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10760 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
10761 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10762
10763 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10764 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10765 * This is needed, because we do not want to rely on relaxed finite resactivities.
10766 */
10767 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
10768
10769 if( agglhs )
10770 {
10771 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10772 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10773
10774 assert(SCIPisLE(scip, minval, maxval));
10775 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
10776 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
10777 {
10778 SCIP_Real oldmaxresactivity;
10779 SCIP_Real oldminresactivity;
10780 SCIP_Bool recalculated;
10781
10782 recalculated = FALSE;
10783 oldmaxresactivity = maxresactivity;
10784 oldminresactivity = minresactivity;
10785
10786 /* check minresactivity for reliability */
10787 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10788 {
10789 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10790 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10791 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10792 }
10793
10794 /* check maxresactivity for reliability */
10795 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10796 {
10797 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10798 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10799 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10800 }
10801
10802 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10803 if( recalculated )
10804 {
10805 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10806
10807 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10808 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10809
10810 assert(SCIPisLE(scip, minval, maxval));
10811 }
10812
10813 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10814 {
10815 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10816 * in the multi-aggregation
10817 */
10818 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10819 {
10820 bestpos = i;
10821 bestisint = isint;
10822 bestislhs = TRUE;
10823 continue; /* no need to also look at the right hand side */
10824 }
10825 }
10826 }
10827 }
10828
10829 if( aggrhs )
10830 {
10831 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10832 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10833
10834 assert(SCIPisLE(scip,minval,maxval));
10835 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
10836 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
10837 {
10838 SCIP_Real oldmaxresactivity;
10839 SCIP_Real oldminresactivity;
10840 SCIP_Bool recalculated;
10841
10842 recalculated = FALSE;
10843 oldmaxresactivity = maxresactivity;
10844 oldminresactivity = minresactivity;
10845
10846 /* check minresactivity for reliability */
10847 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10848 {
10849 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10850 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10851 }
10852
10853 /* check maxresactivity for reliability */
10854 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10855 {
10856 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10857 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10858 }
10859
10860 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10861 if( recalculated )
10862 {
10863 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10864 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10865 assert(SCIPisLE(scip,minval,maxval));
10866 }
10867
10868 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10869 {
10870 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10871 * in the multi-aggregation
10872 */
10873 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10874 {
10875 bestpos = i;
10876 bestisint = isint;
10877 bestislhs = FALSE;
10878 }
10879 }
10880 }
10881 }
10882 }
10883 }
10884
10885 if( bestpos >= 0 )
10886 {
10887 SCIP_VAR** aggrvars;
10888 SCIP_Real* aggrcoefs;
10889 SCIP_Real aggrconst;
10890 SCIP_VAR* bestvar;
10891 SCIP_Real bestval;
10892 int naggrs;
10893 int j;
10894 SCIP_Bool infeasible;
10895 SCIP_Bool aggregated;
10896 SCIP_Bool samevar;
10897 int supinf; /* counter for infinite contributions to the supremum of a possible
10898 * multi-aggregation
10899 */
10900 int infinf; /* counter for infinite contributions to the infimum of a possible
10901 * multi-aggregation
10902 */
10903
10904 assert(!bestislhs || lhsexists);
10905 assert(bestislhs || rhsexists);
10906
10907 bestvar = consdata->vars[bestpos];
10908 bestval = consdata->vals[bestpos];
10909 assert(bestisint ==
10911
10912 /* allocate temporary memory */
10913 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10914 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10915
10916 /* set up the multi-aggregation */
10918 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10919 naggrs = 0;
10920 supinf = 0;
10921 infinf = 0;
10922 samevar = FALSE;
10923
10924 for( j = 0; j < consdata->nvars; ++j )
10925 {
10926 if( j != bestpos )
10927 {
10928 aggrvars[naggrs] = consdata->vars[j];
10929 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10930
10931 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10932
10933 /* do not try to multi aggregate, when numerical bad */
10934 if( SCIPisZero(scip, aggrcoefs[naggrs]) )
10935 {
10936 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10937
10938 /* free temporary memory */
10939 SCIPfreeBufferArray(scip, &aggrcoefs);
10940 SCIPfreeBufferArray(scip, &aggrvars);
10941
10942 return SCIP_OKAY;
10943 }
10944
10945 if( bestisint )
10946 {
10947 /* coefficient must be integral: round it to exact integral value */
10948 assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10949 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10950 }
10951
10952 if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10953 {
10954 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10955 {
10956 ++supinf;
10957 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10958 {
10959 ++infinf;
10960 samevar = TRUE;
10961 }
10962 }
10963 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10964 ++infinf;
10965 }
10966 else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
10967 {
10968 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10969 {
10970 ++supinf;
10971 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10972 {
10973 ++infinf;
10974 samevar = TRUE;
10975 }
10976 }
10977 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10978 ++infinf;
10979 }
10980
10981 naggrs++;
10982 }
10983 }
10984 assert(!samevar || (supinf > 0 && infinf > 0));
10985
10986 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
10987 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
10988 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
10989 assert(naggrs == consdata->nvars-1);
10990
10991 /* right hand side must be integral: round it to exact integral value */
10992 if( bestisint )
10993 {
10994 assert(SCIPisIntegral(scip, aggrconst));
10995 aggrconst = SCIPfloor(scip, aggrconst+0.5);
10996 }
10997
10998 aggregated = FALSE;
10999 infeasible = FALSE;
11000
11001 /* perform the multi-aggregation */
11002 if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11003 {
11004 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11005
11006 /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11007 * the implicitness might rely on the constraint and the integrality of bestvar
11008 */
11009 if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11010 {
11011 SCIP_Bool infeasiblevartypechg;
11012
11013 for( j = 0; j < naggrs; ++j)
11014 {
11015 /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11016 * lead to infeasibility
11017 */
11018 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT )
11019 {
11020 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
11021 (*nchgvartypes)++;
11022 assert(!infeasiblevartypechg);
11023 }
11024 }
11025 }
11026 }
11027 else
11028 {
11029 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11030 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11031 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11032 }
11033 /* free temporary memory */
11034 SCIPfreeBufferArray(scip, &aggrcoefs);
11035 SCIPfreeBufferArray(scip, &aggrvars);
11036
11037 /* check for infeasible aggregation */
11038 if( infeasible )
11039 {
11040 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11041 *cutoff = TRUE;
11042 return SCIP_OKAY;
11043 }
11044
11045 /* delete the constraint, if the aggregation was successful */
11046 if( aggregated )
11047 {
11048 SCIP_CALL( SCIPdelCons(scip, cons) );
11049
11050 if( !consdata->upgraded )
11051 (*ndelconss)++;
11052 (*naggrvars)++;
11053 }
11054 else
11055 {
11056 SCIPdebugMsg(scip, "aggregation non successful!\n");
11057 }
11058 }
11059
11060 return SCIP_OKAY;
11061}
11062
11063#define BINWEIGHT 1
11064#define INTWEIGHT 4
11065#define CONTWEIGHT 8
11066
11067/** gets weight for variable in a "weighted number of variables" sum */
11068static
11070 SCIP_VAR* var /**< variable to get weight for */
11071 )
11072{
11073 switch( SCIPvarGetType(var) )
11074 {
11076 return BINWEIGHT;
11079 return INTWEIGHT;
11081 return CONTWEIGHT;
11082 default:
11083 SCIPerrorMessage("invalid variable type\n");
11084 SCIPABORT();
11085 return 0; /*lint !e527*/
11086 }
11087}
11088
11089/** tries to aggregate variables in equations a^Tx = lhs
11090 * in case there are at most two binary variables with an odd coefficient and all other
11091 * variables are not continuous and have an even coefficient then:
11092 * - exactly one odd binary variables
11093 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11094 * - lhs is odd -> y = 1
11095 * - lhs is even -> y = 0
11096 * - exactly two odd binary variables
11097 * aggregate the two binary variables with odd coefficient
11098 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11099 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11100 */
11101static
11103 SCIP* scip, /**< SCIP data structure */
11104 SCIP_CONS* cons, /**< linear constraint */
11105 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11106 int* nfixedvars, /**< pointer to count number of fixed variables */
11107 int* naggrvars /**< pointer to count number of aggregated variables */
11108 )
11109{ /*lint --e{715}*/
11110 SCIP_CONSDATA* consdata;
11111 SCIP_Bool success;
11112
11113 assert( scip != NULL );
11114 assert( cons != NULL );
11115
11116 consdata = SCIPconsGetData(cons);
11117 assert( consdata != NULL );
11118
11119 /* check if the linear constraint is an equation with integral right hand side */
11120 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11121 return SCIP_OKAY;
11122
11123 /* try to fix and aggregated variables until nothing is possible anymore */
11124 do
11125 {
11126 int v;
11127 int nvars;
11128 SCIP_VAR** vars;
11129 SCIP_Real* vals;
11130 SCIP_Real lhs;
11131 SCIP_Bool lhsodd;
11132
11133 SCIP_Bool infeasible;
11134 SCIP_Bool fixed;
11135 SCIP_Bool aggregated;
11136 SCIP_Bool redundant;
11137
11138 SCIP_VAR* var1;
11139 SCIP_VAR* var2;
11140 int noddvars;
11141
11142 success = FALSE;
11143
11144 lhs = consdata->lhs;
11145 vars = consdata->vars;
11146 vals = consdata->vals;
11147 nvars = consdata->nvars;
11148
11149 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11150
11151 var1 = NULL;
11152 var2 = NULL;
11153 noddvars = 0;
11154
11155 /* search for binary variables with an odd coefficient */
11156 for( v = 0; v < nvars && noddvars < 3; ++v )
11157 {
11158 SCIP_Longint val;
11159
11160 /* all coefficients and variables have to be integral */
11161 if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11162 return SCIP_OKAY;
11163
11164 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11165 if( val % 2 != 0 )
11166 {
11167 /* the odd values have to belong to binary variables */
11168 if( !SCIPvarIsBinary(vars[v]) )
11169 return SCIP_OKAY;
11170
11171 if( noddvars == 0 )
11172 var1 = vars[v];
11173 else
11174 var2 = vars[v];
11175
11176 noddvars++;
11177 }
11178 }
11179
11180 /* check lhs is odd or even */
11181 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11182
11183 if( noddvars == 1 )
11184 {
11185 assert( var1 != NULL );
11186
11187 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11188 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11189
11190 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11191
11192 /* check for infeasibility of fixing */
11193 if( infeasible )
11194 {
11195 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11196 *cutoff = TRUE;
11197 return SCIP_OKAY;
11198 }
11199
11200 if( fixed )
11201 {
11202 SCIPdebugMsg(scip, " -> feasible fixing\n");
11203 (*nfixedvars)++;
11204 success = TRUE;
11205 }
11206 }
11207 else if( noddvars == 2 )
11208 {
11209 assert( var1 != NULL );
11210 assert( var2 != NULL );
11211
11212 /* aggregate the two variables with odd coefficient
11213 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11214 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11215 */
11216 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11217 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11218
11219 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11220 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11221
11222 /* check for infeasibility of aggregation */
11223 if( infeasible )
11224 {
11225 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11226 *cutoff = TRUE;
11227 return SCIP_OKAY;
11228 }
11229
11230 /* count the aggregation */
11231 if( aggregated )
11232 {
11233 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11234 (*naggrvars)++;
11235 success = TRUE;
11236 }
11237 }
11238
11239 if( success )
11240 {
11241 /* apply fixings and aggregation to successfully rerun this presolving step */
11242 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11243
11244 if( infeasible )
11245 {
11246 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11247 *cutoff = TRUE;
11248 return SCIP_OKAY;
11249 }
11250
11251 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11252
11253 if( infeasible )
11254 {
11255 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11256 *cutoff = TRUE;
11257 return SCIP_OKAY;
11258 }
11259 }
11260 }
11261 while( success && consdata->nvars >= 1 );
11262
11263 return SCIP_OKAY;
11264}
11265
11266
11267
11268/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11269 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11270 * coefficients
11271 */
11272static
11274{ /*lint --e{715}*/
11275 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11276 SCIP_VARTYPE vartype1;
11277 SCIP_VARTYPE vartype2;
11278 SCIP_Real value;
11279
11280 assert(consdata != NULL);
11281 assert(0 <= ind1 && ind1 < consdata->nvars);
11282 assert(0 <= ind2 && ind2 < consdata->nvars);
11283
11284 vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11285 vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11286
11287 if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11288 {
11289 /* continuous varibles will be sorted to the back */
11290 if( vartype2 != vartype1 )
11291 return +1;
11292 /* both variables are continuous */
11293 else
11294 return 0;
11295 }
11296 /* continuous variables will be sorted to the back */
11297 else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11298 return -1;
11299
11300 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11301
11302 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11303 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11304}
11305
11306/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11307 *
11308 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11309 * then we can change this constraint to 1^Tx = 1
11310 */
11311static
11313 SCIP* scip, /**< SCIP data structure */
11314 SCIP_CONS* cons, /**< linear constraint */
11315 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11316 int* nchgsides /**< pointer to store the amount of changed sides */
11317 )
11318{
11319 SCIP_CONSDATA* consdata;
11320 SCIP_VAR** vars;
11321 SCIP_Real* vals;
11322 SCIP_Real minval;
11323 SCIP_Real secondminval;
11324 SCIP_Real maxval;
11325 SCIP_Real lhs;
11326 SCIP_Real rhs;
11327 int nvars;
11328 int v;
11329
11330 /* we must not change a modifiable constraint in any way */
11331 if( SCIPconsIsModifiable(cons) )
11332 return SCIP_OKAY;
11333
11334 if( SCIPconsIsDeleted(cons) )
11335 return SCIP_OKAY;
11336
11337 consdata = SCIPconsGetData(cons);
11338 assert(consdata != NULL);
11339
11340 nvars = consdata->nvars;
11341
11342 /* do not check empty or bound-constraints */
11343 if( nvars < 2 )
11344 return SCIP_OKAY;
11345
11346 lhs = consdata->lhs;
11347 rhs = consdata->rhs;
11348 assert(!SCIPisInfinity(scip, -lhs));
11349 assert(!SCIPisInfinity(scip, rhs));
11350 assert(!SCIPisNegative(scip, rhs));
11351
11352 /* sides must be positive and different to detect set partition */
11353 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11354 return SCIP_OKAY;
11355
11356 vals = consdata->vals;
11357 vars = consdata->vars;
11358 assert(vars != NULL);
11359 assert(vals != NULL);
11360
11361 minval = SCIP_INVALID;
11362 secondminval = SCIP_INVALID;
11363 maxval = -SCIP_INVALID;
11364
11365 for( v = nvars - 1; v >= 0; --v )
11366 {
11367 if( SCIPvarIsBinary(vars[v]) )
11368 {
11369 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11370 {
11371 secondminval = minval;
11372 minval = vals[v];
11373 }
11374 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11375 secondminval = vals[v];
11376
11377 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11378 maxval = vals[v];
11379 }
11380 else
11381 break;
11382 }
11383
11384 /* check if all variables are binary, we can choose one, and need to choose at most one */
11385 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11386 && SCIPisGT(scip, minval + secondminval, rhs) )
11387 {
11388 /* change all coefficients to 1.0 */
11389 for( v = nvars - 1; v >= 0; --v )
11390 {
11391 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11392 }
11393 (*nchgcoefs) += nvars;
11394
11395 /* replace old right and left hand side with 1.0 */
11396 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11397 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11398 (*nchgsides) += 2;
11399 }
11400
11401 return SCIP_OKAY;
11402}
11403
11404/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11405 *
11406 * for both-sided constraints only @see rangedRowSimplify() will be called
11407 *
11408 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11409 *
11410 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11411 *
11412 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11413 *
11414 * 2. We try to remove redundant fractional parts in a constraint
11415 *
11416 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11417 *
11418 * 3. We are using the greatest common divisor for further reductions
11419 *
11420 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11421 * integral
11422 */
11423static
11425 SCIP* scip, /**< SCIP data structure */
11426 SCIP_CONS* cons, /**< linear constraint */
11427 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11428 int* nchgsides, /**< pointer to store the amount of changed sides */
11429 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11430 )
11431{
11432 SCIP_CONSDATA* consdata;
11433 SCIP_VAR** vars;
11434 SCIP_Real* vals;
11435 int* perm;
11436 SCIP_Real minactsub;
11437 SCIP_Real maxactsub;
11438 SCIP_Real siderest;
11439 SCIP_Real feastol;
11440 SCIP_Real newcoef;
11441 SCIP_Real absval;
11442 SCIP_Real minact;
11443 SCIP_Real maxact;
11444 SCIP_Real side;
11445 SCIP_Real lhs;
11446 SCIP_Real rhs;
11447 SCIP_Real lb;
11448 SCIP_Real ub;
11449 SCIP_Longint restcoef;
11450 SCIP_Longint oldgcd;
11451 SCIP_Longint rest;
11452 SCIP_Longint gcd;
11453 SCIP_Bool isminsettoinfinity;
11454 SCIP_Bool ismaxsettoinfinity;
11455 SCIP_Bool ismintight;
11456 SCIP_Bool ismaxtight;
11457 SCIP_Bool allcoefintegral;
11458 SCIP_Bool onlybin;
11459 SCIP_Bool hasrhs;
11460 SCIP_Bool haslhs;
11461 int oldnchgcoefs; /* cppcheck-suppress unassignedVariable */
11462 int oldnchgsides; /* cppcheck-suppress unassignedVariable */
11463 int foundbin;
11464 int candpos;
11465 int candpos2;
11466 int offsetv;
11467 int nvars;
11468 int v;
11469 int w;
11470
11471 assert(scip != NULL);
11472 assert(cons != NULL);
11473 assert(nchgcoefs != NULL);
11474 assert(nchgsides != NULL);
11475
11476 *infeasible = FALSE;
11477
11478 /* we must not change a modifiable constraint in any way */
11479 if( SCIPconsIsModifiable(cons) )
11480 return SCIP_OKAY;
11481
11482 if( SCIPconsIsDeleted(cons) )
11483 return SCIP_OKAY;
11484
11485 consdata = SCIPconsGetData(cons);
11486 assert(consdata != NULL);
11487
11488 nvars = consdata->nvars;
11489
11490 /* do not check empty or bound-constraints */
11491 if( nvars <= 2 )
11492 return SCIP_OKAY;
11493
11494 /* update maximal activity delta if necessary */
11495 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11497
11498 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11499 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11500 checkMaxActivityDelta(scip, consdata);
11501
11502 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11503 * accordingly
11504 */
11505 /* can only work with valid non-infinity activities per variable */
11506 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11507 return SCIP_OKAY;
11508
11509 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11510 * but the eventsystem seems to be full
11511 */
11512 consdata->normalized = FALSE;
11513
11514 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11515 assert(nvars == consdata->nvars);
11516
11517 if( *infeasible )
11518 return SCIP_OKAY;
11519
11520 if( !consdata->normalized )
11521 return SCIP_OKAY;
11522
11523 lhs = consdata->lhs;
11524 rhs = consdata->rhs;
11525 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11526 assert(!SCIPisNegative(scip, rhs));
11527
11528 if( !SCIPisInfinity(scip, -lhs) )
11529 haslhs = TRUE;
11530 else
11531 haslhs = FALSE;
11532
11533 if( !SCIPisInfinity(scip, rhs) )
11534 hasrhs = TRUE;
11535 else
11536 hasrhs = FALSE;
11537
11538 /* @todo extend both-sided simplification */
11539 if( haslhs && hasrhs )
11540 {
11541 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11542
11543 return SCIP_OKAY;
11544 }
11545 assert(haslhs != hasrhs);
11546
11547 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11548 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11549 assert(!haslhs || !SCIPisNegative(scip, lhs));
11550
11551 /* get temporary memory to store the sorted permutation */
11552 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11553
11554 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11555 * value of their coefficients
11556 */
11557 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11558
11559 /* perform sorting after permutation array */
11560 permSortConsdata(consdata, perm, nvars);
11561 consdata->indexsorted = FALSE;
11562 consdata->coefsorted = FALSE;
11563
11564 vars = consdata->vars;
11565 vals = consdata->vals;
11566 assert(vars != NULL);
11567 assert(vals != NULL);
11568 assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11569
11570 /* free temporary memory */
11571 SCIPfreeBufferArray(scip, &perm);
11572
11573 /* only check constraints with at least two non continuous variables */
11574 if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11575 return SCIP_OKAY;
11576
11577 /* do not process constraints when all coefficients are 1.0 */
11578 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11579 return SCIP_OKAY;
11580
11581 feastol = SCIPfeastol(scip);
11582
11583 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11585
11586 /* get global activities */
11587 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11588 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
11589
11590 /* cannot work with infinite activities */
11591 if( isminsettoinfinity || ismaxsettoinfinity )
11592 return SCIP_OKAY;
11593
11594 assert(ismintight);
11595 assert(ismaxtight);
11596 assert(maxact > minact);
11597 assert(!SCIPisInfinity(scip, -minact));
11598 assert(!SCIPisInfinity(scip, maxact));
11599
11600 v = 0;
11601 offsetv = -1;
11602 side = haslhs ? lhs : rhs;
11603 minactsub = minact;
11604 maxactsub = maxact;
11605
11606 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11607 * do not need to look at the large coefficients
11608 *
11609 * e.g. all x are binary, z are positive integer
11610 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11611 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11612 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11613 *
11614 * can be changed to
11615 *
11616 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11617 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11618 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11619 */
11620
11621 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11622 * hand side, we cannot apply the extra reduction step and need to reset v
11623 *
11624 * 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
11625 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11626 * for all i is a solution
11627 *
11628 * also redundancy of variables would not be correctly determined in such a case
11629 */
11630 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11631 {
11632 v = 1;
11633
11634 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11635 {
11636 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11637 * extra step, which might have worked
11638 */
11639 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11640 {
11641 v = 0;
11642 break;
11643 }
11644
11645 ++v;
11646 }
11647
11648 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11649 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11650 if( v == nvars )
11651 return SCIP_OKAY;
11652
11653 /* cannot work with continuous variables which have a big coefficient */
11654 if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11655 return SCIP_OKAY;
11656
11657 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11658 if( SCIPisEQ(scip, side, -vals[v]) )
11659 v = 0;
11660
11661 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11662 * reduction
11663 */
11664 if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11665 v = 0;
11666
11667 if( v > 0 )
11668 {
11669 assert(v < nvars);
11670
11671 offsetv = v - 1;
11672
11673 for( w = 0; w < v; ++w )
11674 {
11675 lb = SCIPvarGetLbGlobal(vars[w]);
11676 ub = SCIPvarGetUbGlobal(vars[w]);
11677
11678 assert(vals[w] > 0);
11679
11680 /* update residual activities */
11681 maxactsub -= ub * vals[w];
11682 minactsub -= lb * vals[w];
11683 assert(maxactsub > minactsub);
11684 }
11685 }
11686 }
11687
11688 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11689 *
11690 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11691 *
11692 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11693 * to
11694 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11695 */
11696 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11697 {
11698 SCIP_Bool redundant = FALSE;
11699 SCIP_Bool numericsok;
11700 SCIP_Bool rredundant;
11701 SCIP_Bool lredundant;
11702
11703 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11704 assert(gcd >= 1);
11705
11706 if( v == 0 )
11707 {
11708 lb = SCIPvarGetLbGlobal(vars[0]);
11709 ub = SCIPvarGetUbGlobal(vars[0]);
11710
11711 /* update residual activities */
11712 if( vals[0] > 0 )
11713 {
11714 maxactsub -= ub * vals[0];
11715 minactsub -= lb * vals[0];
11716 }
11717 else
11718 {
11719 maxactsub -= lb * vals[0];
11720 minactsub -= ub * vals[0];
11721 }
11722 assert(maxactsub > minactsub);
11723 ++v;
11724 }
11725
11726 siderest = -SCIP_INVALID;
11727 allcoefintegral = TRUE;
11728
11729 /* check if some variables always fit into the given constraint */
11730 for( ; v < nvars - 1; ++v )
11731 {
11732 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11733 break;
11734
11735 if( !SCIPisIntegral(scip, vals[v]) )
11736 {
11737 allcoefintegral = FALSE;
11738 break;
11739 }
11740
11741 /* calculate greatest common divisor for all general and binary variables */
11742 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11743
11744 if( gcd == 1 )
11745 break;
11746
11747 lb = SCIPvarGetLbGlobal(vars[v]);
11748 ub = SCIPvarGetUbGlobal(vars[v]);
11749
11750 assert(!SCIPisInfinity(scip, -lb));
11751 assert(!SCIPisInfinity(scip, ub));
11752
11753 /* update residual activities */
11754 if( vals[v] > 0 )
11755 {
11756 maxactsub -= ub * vals[v];
11757 minactsub -= lb * vals[v];
11758 }
11759 else
11760 {
11761 maxactsub -= lb * vals[v];
11762 minactsub -= ub * vals[v];
11763 }
11764 assert(SCIPisGE(scip, maxactsub, minactsub));
11765
11766 if( hasrhs )
11767 {
11768 /* determine the remainder of the right hand side and the gcd */
11769 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11770 }
11771 else
11772 {
11773 /* determine the remainder of the left hand side and the gcd */
11774 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11775 if( SCIPisZero(scip, siderest) )
11776 siderest = gcd;
11777 }
11778
11779 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11780 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11781
11782 /* early termination if the activities deceed the gcd */
11783 if( offsetv == -1 && (rredundant || lredundant) )
11784 {
11785 redundant = TRUE;
11786 break;
11787 }
11788 }
11789 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11790
11791 if( !redundant )
11792 {
11793 if( hasrhs )
11794 {
11795 /* determine the remainder of the right hand side and the gcd */
11796 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11797 }
11798 else
11799 {
11800 /* determine the remainder of the left hand side and the gcd */
11801 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11802 if( SCIPisZero(scip, siderest) )
11803 siderest = gcd;
11804 }
11805 }
11806 else
11807 ++v;
11808
11809 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",
11810 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11811
11812 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11813 * reasonable absolute values */
11814 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11815 REALABS(minactsub) < MAXACTVAL;
11816
11817 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11818 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11819
11820 /* check if we can remove redundant variables */
11821 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11822 {
11823 SCIP_Real oldcoef;
11824
11825 /* double check the redundancy */
11826#ifndef NDEBUG
11827 SCIP_Real tmpminactsub = 0.0;
11828 SCIP_Real tmpmaxactsub = 0.0;
11829
11830 /* recompute residual activities */
11831 for( w = v; w < nvars; ++w )
11832 {
11833 lb = SCIPvarGetLbGlobal(vars[w]);
11834 ub = SCIPvarGetUbGlobal(vars[w]);
11835
11836 assert(!SCIPisInfinity(scip, -lb));
11837 assert(!SCIPisInfinity(scip, ub));
11838
11839 /* update residual activities */
11840 if( vals[w] > 0 )
11841 {
11842 tmpmaxactsub += ub * vals[w];
11843 tmpminactsub += lb * vals[w];
11844 }
11845 else
11846 {
11847 tmpmaxactsub += lb * vals[w];
11848 tmpminactsub += ub * vals[w];
11849 }
11850 assert(tmpmaxactsub >= tmpminactsub);
11851 }
11852
11853 if( hasrhs )
11854 {
11855 assert(offsetv == -1);
11856
11857 /* determine the remainder of the right hand side and the gcd */
11858 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11859 }
11860 else
11861 {
11862 /* determine the remainder of the left hand side and the gcd */
11863 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11864 if( SCIPisZero(scip, siderest) )
11865 siderest = gcd;
11866 }
11867
11868 /* is the redundancy really fulfilled */
11869 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11870 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11871#endif
11872
11873 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11874 nvars - v, SCIPconsGetName(cons));
11875
11876 /* remove redundant variables */
11877 for( w = nvars - 1; w >= v; --w )
11878 {
11879 SCIP_CALL( delCoefPos(scip, cons, w) );
11880 }
11881 (*nchgcoefs) += (nvars - v);
11882
11883 assert(w >= 0);
11884
11885 oldcoef = vals[w];
11886
11887 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11888 assert(vars == consdata->vars);
11889 assert(vals == consdata->vals);
11890 assert(w < consdata->nvars);
11891
11892 if( *infeasible )
11893 return SCIP_OKAY;
11894
11895 /* compute new greatest common divisor due to normalization */
11896 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11897 assert(gcd >= 1);
11898
11899 /* update side */
11900 if( hasrhs )
11901 {
11902 /* replace old with new right hand side */
11903 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11904 rhs = consdata->rhs;
11905 }
11906 else
11907 {
11908 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11909 {
11910 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11911 lhs = consdata->lhs;
11912 }
11913 else
11914 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11915 }
11916 ++(*nchgsides);
11917
11918 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11919 assert(!haslhs || !SCIPisNegative(scip, lhs));
11920
11921 /* get new constraint data */
11922 nvars = consdata->nvars;
11923 assert(nvars > 0);
11924
11925 allcoefintegral = TRUE;
11926
11927#ifndef NDEBUG
11928 /* check integrality */
11929 for( w = offsetv + 1; w < nvars; ++w )
11930 {
11931 assert(SCIPisIntegral(scip, vals[w]));
11932 }
11933#endif
11935 }
11936
11937 /* try to find a better gcd, when having large coefficients */
11938 if( offsetv >= 0 && gcd == 1 )
11939 {
11940 /* calculate greatest common divisor for all general variables */
11941 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11942
11943 if( gcd > 1 )
11944 {
11945 gcd = -1;
11946 candpos = -1;
11947
11948 for( v = nvars - 1; v > offsetv; --v )
11949 {
11950 assert(!SCIPisZero(scip, vals[v]));
11951 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11952 break;
11953
11954 if( !SCIPisIntegral(scip, vals[v]) )
11955 {
11956 allcoefintegral = FALSE;
11957 break;
11958 }
11959
11960 oldgcd = gcd;
11961
11962 if( gcd == -1 )
11963 {
11964 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11965 assert(gcd >= 1);
11966 }
11967 else
11968 {
11969 /* calculate greatest common divisor for all general and binary variables */
11970 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11971 }
11972
11973 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11974 * can stop searching
11975 */
11976 if( gcd == 1 )
11977 {
11978 if( !SCIPvarIsBinary(vars[v]) )
11979 break;
11980
11981 /* found candidate */
11982 if( candpos == -1 )
11983 {
11984 gcd = oldgcd;
11985 candpos = v;
11986 }
11987 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
11988 else
11989 break;
11990 }
11991 }
11992 assert(v > offsetv || candpos > offsetv);
11993 }
11994 else
11995 candpos = -1;
11996 }
11997 else
11998 candpos = nvars - 1;
11999
12000 /* check last coefficient for integrality */
12001 if( gcd > 1 && allcoefintegral && !redundant )
12002 {
12003 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12004 allcoefintegral = FALSE;
12005 }
12006
12007 /* check for further necessary coefficient adjustments */
12008 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12009 {
12010 assert(offsetv + 1 < nvars);
12011 assert(0 <= candpos && candpos < nvars);
12012
12013 if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12014 {
12015 SCIP_Bool notchangable = FALSE;
12016
12017#ifndef NDEBUG
12018 /* check integrality */
12019 for( w = offsetv + 1; w < nvars; ++w )
12020 {
12021 assert(SCIPisIntegral(scip, vals[w]));
12022 }
12023#endif
12024
12025 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12026 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12027 {
12028 /* determine the remainder of the side and the gcd */
12029 if( hasrhs )
12030 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12031 else
12032 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12033 assert(rest >= 0);
12034 assert(rest < gcd);
12035
12036 /* determine the remainder of the coefficient candidate and the gcd */
12037 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12038 assert(restcoef >= 1);
12039 assert(restcoef < gcd);
12040
12041 if( hasrhs )
12042 {
12043 /* calculate new coefficient */
12044 if( restcoef > rest )
12045 newcoef = vals[candpos] - restcoef + gcd;
12046 else
12047 newcoef = vals[candpos] - restcoef;
12048 }
12049 else
12050 {
12051 /* calculate new coefficient */
12052 if( rest == 0 || restcoef < rest )
12053 newcoef = vals[candpos] - restcoef;
12054 else
12055 newcoef = vals[candpos] - restcoef + gcd;
12056 }
12057
12058 /* done */
12059
12060 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12061 * another with the big coefficient was set to 1
12062 */
12063 if( hasrhs && SCIPisZero(scip, newcoef) )
12064 {
12065 notchangable = TRUE;
12066 }
12067 else if( SCIPisZero(scip, newcoef) )
12068 {
12069 /* delete old redundant coefficient */
12070 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12071 ++(*nchgcoefs);
12072 }
12073 else
12074 {
12075 /* replace old with new coefficient */
12076 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12077 ++(*nchgcoefs);
12078 }
12079 }
12080 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12081 {
12082 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12083 }
12084
12085 /* correct side and big coefficients */
12086 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12087 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12088 {
12089 if( haslhs )
12090 {
12091 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12092
12093 SCIP_CALL( chgLhs(scip, cons, newcoef) );
12094 ++(*nchgsides);
12095 }
12096 else
12097 {
12098 assert(hasrhs);
12099 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12100
12101 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12102 ++(*nchgsides);
12103 }
12104
12105 /* correct coefficients up front */
12106 for( w = offsetv; w >= 0; --w )
12107 {
12108 assert(vals[w] > 0);
12109
12110 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12111 }
12112 (*nchgcoefs) += (offsetv + 1);
12113 }
12114
12115 if( !notchangable )
12116 {
12117 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12118 assert(vars == consdata->vars);
12119 assert(vals == consdata->vals);
12120
12121 if( *infeasible )
12122 return SCIP_OKAY;
12123
12124 /* get new constraint data */
12125 nvars = consdata->nvars;
12126 assert(nvars >= 2);
12127
12129
12130 lhs = consdata->lhs;
12131 rhs = consdata->rhs;
12132 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12133 assert(!haslhs || !SCIPisNegative(scip, lhs));
12134 }
12135 }
12136 }
12137 }
12138
12139 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12140 /* no continuous variables are left over */
12141 if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12142 return SCIP_OKAY;
12143
12144 onlybin = TRUE;
12145 allcoefintegral = TRUE;
12146 /* check if all variables are of binary type */
12147 for( v = nvars - 1; v >= 0; --v )
12148 {
12149 if( !SCIPvarIsBinary(vars[v]) )
12150 onlybin = FALSE;
12151 if( !SCIPisIntegral(scip, vals[v]) )
12152 allcoefintegral = FALSE;
12153 }
12154
12155 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12156 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12157 *
12158 * @todo there are some steps missing ....
12159 */
12160 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12161 {
12162 SCIP_Real val;
12163 SCIP_Real newval;
12164 SCIP_Real frac = 0.0;
12165 SCIP_Bool found = FALSE;
12166
12167 if( hasrhs )
12168 {
12169 if( allcoefintegral )
12170 {
12171 /* replace old with new right hand side */
12172 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12173 ++(*nchgsides);
12174 }
12175 else
12176 {
12177 siderest = rhs - SCIPfloor(scip, rhs);
12178
12179 /* try to round down all non-integral coefficients */
12180 for( v = nvars - 1; v >= 0; --v )
12181 {
12182 val = vals[v];
12183
12184 /* add up all possible fractional parts */
12185 if( !SCIPisIntegral(scip, val) )
12186 {
12187 lb = SCIPvarGetLbGlobal(vars[v]);
12188 ub = SCIPvarGetUbGlobal(vars[v]);
12189
12190 /* at least one bound need to be at zero */
12191 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12192 return SCIP_OKAY;
12193
12194 /* swap bounds for 'standard' form */
12195 if( !SCIPisFeasZero(scip, lb) )
12196 {
12197 ub = -lb;
12198 val *= -1;
12199 }
12200
12201 found = TRUE;
12202
12203 frac += (val - SCIPfloor(scip, val)) * ub;
12204
12205 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12206 *
12207 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12208 * x3, x4 set to 1 would be infeasible but feasible after flooring
12209 */
12210 if( SCIPisGT(scip, frac, siderest) )
12211 return SCIP_OKAY;
12212 }
12213 }
12214 assert(v == -1);
12215
12216 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12217
12218 /* round rhs and coefficients to integral values */
12219 if( found )
12220 {
12221 for( v = nvars - 1; v >= 0; --v )
12222 {
12223 val = vals[v];
12224
12225 /* add the whole fractional part */
12226 if( !SCIPisIntegral(scip, val) )
12227 {
12228 lb = SCIPvarGetLbGlobal(vars[v]);
12229
12230 if( SCIPisFeasZero(scip, lb) )
12231 newval = SCIPfloor(scip, val);
12232 else
12233 newval = SCIPceil(scip, val);
12234
12235 if( SCIPisZero(scip, newval) )
12236 {
12237 /* delete old redundant coefficient */
12238 SCIP_CALL( delCoefPos(scip, cons, v) );
12239 ++(*nchgcoefs);
12240 }
12241 else
12242 {
12243 /* replace old with new coefficient */
12244 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12245 ++(*nchgcoefs);
12246 }
12247 }
12248 }
12249 }
12250
12251 /* replace old with new right hand side */
12252 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12253 ++(*nchgsides);
12254 }
12255 }
12256 else
12257 {
12258 if( allcoefintegral )
12259 {
12260 /* replace old with new left hand side */
12261 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12262 ++(*nchgsides);
12263 }
12264 else
12265 {
12266 /* cannot floor left hand side to zero */
12267 if( SCIPisLT(scip, lhs, 1.0) )
12268 return SCIP_OKAY;
12269
12270 siderest = lhs - SCIPfloor(scip, lhs);
12271
12272 /* try to round down all non-integral coefficients */
12273 for( v = nvars - 1; v >= 0; --v )
12274 {
12275 val = vals[v];
12276
12277 /* add up all possible fractional parts */
12278 if( !SCIPisIntegral(scip, val) )
12279 {
12280 lb = SCIPvarGetLbGlobal(vars[v]);
12281 ub = SCIPvarGetUbGlobal(vars[v]);
12282
12283 /* at least one bound need to be at zero */
12284 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12285 return SCIP_OKAY;
12286
12287 /* swap bounds for 'standard' form */
12288 if( !SCIPisFeasZero(scip, lb) )
12289 {
12290 ub = -lb;
12291 val *= -1;
12292 }
12293
12294 /* cannot floor to zero */
12295 if( SCIPisLT(scip, val, 1.0) )
12296 return SCIP_OKAY;
12297
12298 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12299 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12300 return SCIP_OKAY;
12301
12302 found = TRUE;
12303
12304 frac += (val - SCIPfloor(scip, val)) * ub;
12305
12306 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12307 * fractional parts of the variables, we cannot tighten the coefficients
12308 *
12309 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12310 * x2-x4 set to 1 would be feasible but not after flooring
12311 */
12312 if( SCIPisGE(scip, frac, 1 + siderest) )
12313 return SCIP_OKAY;
12314 }
12315 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12316 else
12317 return SCIP_OKAY;
12318 }
12319 assert(v == -1);
12320
12321 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12322
12323 /* round lhs and coefficients to integral values */
12324 if( found )
12325 {
12326 for( v = nvars - 1; v >= 0; --v )
12327 {
12328 val = vals[v];
12329
12330 /* add the whole fractional part */
12331 if( !SCIPisIntegral(scip, val) )
12332 {
12333 lb = SCIPvarGetLbGlobal(vars[v]);
12334
12335 if( SCIPisFeasZero(scip, lb) )
12336 newval = SCIPfloor(scip, val);
12337 else
12338 newval = SCIPceil(scip, val);
12339
12340 if( SCIPisZero(scip, newval) )
12341 {
12342 /* delete old redundant coefficient */
12343 SCIP_CALL( delCoefPos(scip, cons, v) );
12344 ++(*nchgcoefs);
12345 }
12346 else
12347 {
12348 /* replace old with new coefficient */
12349 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12350 ++(*nchgcoefs);
12351 }
12352 }
12353 }
12354 }
12355
12356 /* replace old with new left hand side */
12357 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12358 ++(*nchgsides);
12359 }
12360 }
12361
12362 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12363 assert(vars == consdata->vars);
12364 assert(vals == consdata->vals);
12365
12366 if( *infeasible )
12367 return SCIP_OKAY;
12368
12369 rhs = consdata->rhs;
12370 lhs = consdata->lhs;
12371
12372 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12373 assert(!haslhs || !SCIPisNegative(scip, lhs));
12374
12376
12377 nvars = consdata->nvars;
12378 if( nvars < 2 )
12379 return SCIP_OKAY;
12380
12381 allcoefintegral = TRUE;
12382#ifndef NDEBUG
12383 /* debug check if all coefficients are really integral */
12384 for( v = nvars - 1; v >= 0; --v )
12385 assert(SCIPisIntegral(scip, vals[v]));
12386#endif
12387 }
12388
12389 /* @todo following can also work on non integral coefficients, need more investigation */
12390 /* only check constraints with integral coefficients on all integral variables */
12391 if( !allcoefintegral )
12392 return SCIP_OKAY;
12393
12394 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12395 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12396 return SCIP_OKAY;
12397
12398 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12399 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12400 return SCIP_OKAY;
12401
12402 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12403 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12404 return SCIP_OKAY;
12405
12406 assert(nvars >= 2);
12407
12408 /* start gcd procedure for all variables */
12409 do
12410 {
12411 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12412 SCIPdebug( oldnchgsides = *nchgsides; )
12413
12414 /* stop if we have two coeffcients which are one in absolute value */
12415 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12416 return SCIP_OKAY;
12417
12418 gcd = -1;
12419
12420 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12421 * because coefficients of non-binary variables might have changed to zero */
12422 if( !onlybin )
12423 {
12424 foundbin = -1;
12425 onlybin = TRUE;
12426
12427 for( v = nvars - 1; v >= 0; --v )
12428 {
12429 assert(!SCIPisZero(scip, vals[v]));
12430 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12431
12432 if( SCIPvarIsBinary(vars[v]) )
12433 {
12434 if( foundbin == -1 )
12435 foundbin = v;
12436 continue;
12437 }
12438 else
12439 onlybin = FALSE;
12440
12441 absval = REALABS(vals[v]);
12442 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12443 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12444 */
12445 assert(SCIPisFeasIntegral(scip, absval));
12446
12447 if( gcd == -1 )
12448 {
12449 gcd = (SCIP_Longint)(absval + feastol);
12450 assert(gcd >= 1);
12451 }
12452 else
12453 {
12454 /* calculate greatest common divisor for all general variables */
12455 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12456 }
12457 if( gcd == 1 )
12458 break;
12459 }
12460 }
12461 else
12462 foundbin = nvars - 1;
12463
12464 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12465 if( gcd == 1 || foundbin == -1)
12466 return SCIP_OKAY;
12467
12468 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12469
12470 candpos = -1;
12471 candpos2 = -1;
12472
12473 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12474 * change the coefficient
12475 */
12476 for( v = foundbin; v >= 0; --v )
12477 {
12478 if( onlybin || SCIPvarIsBinary(vars[v]) )
12479 {
12480 absval = REALABS(vals[v]);
12481 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12482 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12483 */
12484 assert(SCIPisFeasIntegral(scip, absval));
12485
12486 oldgcd = gcd;
12487
12488 if( gcd == -1 )
12489 {
12490 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12491 assert(gcd >= 1);
12492 }
12493 else
12494 {
12495 /* calculate greatest common divisor for all general and binary variables */
12496 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12497 }
12498
12499 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12500 * can terminate
12501 */
12502 if( gcd == 1 )
12503 {
12504 /* found candidate */
12505 if( candpos == -1 )
12506 {
12507 gcd = oldgcd;
12508 candpos = v;
12509
12510 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12511 * the coefficient change
12512 */
12513 if( onlybin && v == foundbin - 1 )
12514 candpos2 = foundbin;
12515 }
12516 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12517 else
12518 {
12519 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12520 {
12521 assert(candpos2 == nvars - 1);
12522
12523 /* take new candidates */
12524 candpos = candpos2;
12525
12526 /* recalculate gcd from scratch */
12527 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12528 assert(gcd >= 1);
12529
12530 /* calculate greatest common divisor for all general and binary variables */
12531 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12532 if( gcd == 1 )
12533 return SCIP_OKAY;
12534 }
12535 else
12536 /* cannot determine a possible coefficient for reduction */
12537 return SCIP_OKAY;
12538 }
12539 }
12540 }
12541 }
12542 assert(gcd >= 2);
12543
12544 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12545 * further
12546 */
12547 assert(candpos >= 0 && candpos < nvars);
12548
12549 /* all variables and all coefficients are integral, so the side should be too */
12550 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12551
12552 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12553 * @see normalizeCons()
12554 */
12555 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12556 assert(!haslhs || !SCIPisNegative(scip, lhs));
12557
12558 /* determine the remainder of the side and the gcd */
12559 if( hasrhs )
12560 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12561 else
12562 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12563 assert(rest >= 0);
12564 assert(rest < gcd);
12565
12566 /* determine the remainder of the coefficient candidate and the gcd */
12567 if( vals[candpos] < 0 )
12568 {
12569 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12570 assert(restcoef <= -1);
12571 restcoef += gcd;
12572 }
12573 else
12574 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12575 assert(restcoef >= 1);
12576 assert(restcoef < gcd);
12577
12578 if( hasrhs )
12579 {
12580 if( rest > 0 )
12581 {
12582 /* replace old with new right hand side */
12583 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12584 ++(*nchgsides);
12585 }
12586
12587 /* calculate new coefficient */
12588 if( restcoef > rest )
12589 newcoef = vals[candpos] - restcoef + gcd;
12590 else
12591 newcoef = vals[candpos] - restcoef;
12592 }
12593 else
12594 {
12595 if( rest > 0 )
12596 {
12597 /* replace old with new left hand side */
12598 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12599 ++(*nchgsides);
12600 }
12601
12602 /* calculate new coefficient */
12603 if( rest == 0 || restcoef < rest )
12604 newcoef = vals[candpos] - restcoef;
12605 else
12606 newcoef = vals[candpos] - restcoef + gcd;
12607 }
12608 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12609
12610 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));
12611
12612 if( SCIPisZero(scip, newcoef) )
12613 {
12614 /* delete redundant coefficient */
12615 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12616 }
12617 else
12618 {
12619 /* replace old with new coefficient */
12620 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12621 }
12622 ++(*nchgcoefs);
12623
12624 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12625 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12626 assert(vars == consdata->vars);
12627 assert(vals == consdata->vals);
12628
12629 if( *infeasible )
12630 return SCIP_OKAY;
12631
12633
12634 rhs = consdata->rhs;
12635 lhs = consdata->lhs;
12636 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12637 assert(!haslhs || !SCIPisNegative(scip, lhs));
12638
12639 nvars = consdata->nvars;
12640
12641 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));
12642 }
12643 while( nvars >= 2 );
12644
12645 return SCIP_OKAY;
12646}
12647
12648
12649/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12650 * cons0 := a * cons0 + b * cons1,
12651 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12652 * for numerical stability, we will only accept integral a and b;
12653 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12654 * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12655 */
12656static
12658 SCIP* scip, /**< SCIP data structure */
12659 SCIP_CONS* cons0, /**< (in)equality to modify */
12660 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12661 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12662 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12663 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12664 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12665 int nvarscommon, /**< number of variables, that appear in both constraints */
12666 int commonidxweight, /**< variable weight sum of common variables */
12667 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12668 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12669 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12670 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12671 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12672 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12673 )
12674{
12675 SCIP_CONSDATA* consdata0;
12676 SCIP_CONSDATA* consdata1;
12677 SCIP_Real a;
12678 SCIP_Real b;
12679 SCIP_Real aggrcoef;
12680 SCIP_Real scalarsum;
12681 SCIP_Real bestscalarsum;
12682 SCIP_Bool betterscalarsum;
12683 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12684 int varweight;
12685 int nvars;
12686 int bestvarweight;
12687 int bestnvars;
12688 int bestv;
12689 int v;
12690 int i;
12691
12692 assert(scip != NULL);
12693 assert(cons0 != NULL);
12694 assert(cons1 != NULL);
12695 assert(commonidx0 != NULL);
12696 assert(commonidx1 != NULL);
12697 assert(diffidx0minus1 != NULL);
12698 assert(diffidx1minus0 != NULL);
12699 assert(nvarscommon >= 1);
12700 assert(commonidxweight >= nvarscommon);
12701 assert(nchgcoefs != NULL);
12702 assert(aggregated != NULL);
12703
12704 assert(SCIPconsIsActive(cons0));
12705 assert(SCIPconsIsActive(cons1));
12706
12707 *infeasible = FALSE;
12708
12709 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12710
12711 /* cons0 is an (in)equality */
12712 consdata0 = SCIPconsGetData(cons0);
12713 assert(consdata0 != NULL);
12714 assert(consdata0->nvars >= 1);
12715 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12716 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12717
12718 /* cons1 is an equality */
12719 consdata1 = SCIPconsGetData(cons1);
12720 assert(consdata1 != NULL);
12721 assert(consdata1->nvars >= 1);
12722 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12723 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12724
12725 *aggregated = FALSE;
12726
12727 /* search for the best common variable such that
12728 * val1[var] * consdata0 - val0[var] * consdata1
12729 * has least weighted number of variables
12730 */
12731 bestvarweight = commonidxweight + diffidx0minus1weight;
12732 bestnvars = consdata0->nvars;
12733 bestv = -1;
12734 bestscalarsum = 0.0;
12735 commonvarlindependent = TRUE;
12736 for( v = 0; v < nvarscommon; ++v )
12737 {
12738 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12739 a = consdata1->vals[commonidx1[v]];
12740 b = -consdata0->vals[commonidx0[v]];
12741
12742 /* only try aggregation, if coefficients are integral (numerical stability) */
12744 {
12745 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12746 varweight = diffidx0minus1weight + diffidx1minus0weight;
12747 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12748 scalarsum = REALABS(a) + REALABS(b);
12749 betterscalarsum = (scalarsum < bestscalarsum);
12750 for( i = 0; i < nvarscommon
12751 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12752 {
12753 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12754 if( !SCIPisZero(scip, aggrcoef) )
12755 {
12756 varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12757 nvars++;
12758 }
12759 }
12760 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12761 {
12762 bestv = v;
12763 bestvarweight = varweight;
12764 bestnvars = nvars;
12765 bestscalarsum = scalarsum;
12766 }
12767 }
12768
12769 /* update commonvarlindependent flag, if still TRUE:
12770 * 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
12771 */
12772 if( commonvarlindependent && v > 0 )
12773 commonvarlindependent = SCIPisEQ(scip,
12774 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12775 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12776 }
12777
12778 /* if better aggregation was found, create new constraint and delete old one */
12779 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12780 {
12781 SCIP_CONS* newcons;
12782 SCIP_CONSDATA* newconsdata;
12783 SCIP_VAR** newvars;
12784 SCIP_Real* newvals;
12785 SCIP_Real newlhs;
12786 SCIP_Real newrhs;
12787 int newnvars;
12788
12789 if( bestv != -1 )
12790 {
12791 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12792 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12793 {
12794 a = consdata1->vals[commonidx1[bestv]];
12795 b = -consdata0->vals[commonidx0[bestv]];
12796 }
12797 else
12798 {
12799 a = -consdata1->vals[commonidx1[bestv]];
12800 b = consdata0->vals[commonidx0[bestv]];
12801 }
12802 assert(SCIPisIntegral(scip, a));
12803 assert(SCIPisPositive(scip, a));
12804 assert(SCIPisIntegral(scip, b));
12805 assert(!SCIPisZero(scip, b));
12806 }
12807 else
12808 {
12809 assert(commonvarlindependent);
12810 if( consdata1->vals[commonidx1[0]] > 0.0 )
12811 {
12812 a = consdata1->vals[commonidx1[0]];
12813 b = -consdata0->vals[commonidx0[0]];
12814 }
12815 else
12816 {
12817 a = -consdata1->vals[commonidx1[0]];
12818 b = consdata0->vals[commonidx0[0]];
12819 }
12820 assert(SCIPisPositive(scip, a));
12821 assert(!SCIPisZero(scip, b));
12822
12823 /* if a/b is integral, then we can easily choose integer multipliers */
12824 if( SCIPisIntegral(scip, a/b) )
12825 {
12826 if( a/b > 0 )
12827 {
12828 a /= b;
12829 b = 1.0;
12830 }
12831 else
12832 {
12833 a /= -b;
12834 b = -1.0;
12835 }
12836 }
12837
12838 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12839 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12840 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12841 }
12842
12843 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12844 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12845 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12846 SCIPdebugPrintCons(scip, cons0, NULL);
12847 SCIPdebugPrintCons(scip, cons1, NULL);
12848
12849 /* get temporary memory for creating the new linear constraint */
12850 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12851 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12852
12853 /* calculate the common coefficients, if we have not recognized linear dependency */
12854 newnvars = 0;
12855 if( !commonvarlindependent )
12856 {
12857 for( i = 0; i < nvarscommon; ++i )
12858 {
12859 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12860 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12861
12862 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12863 if( !SCIPisZero(scip, aggrcoef) )
12864 {
12865 assert(newnvars < bestnvars);
12866 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12867 newvals[newnvars] = aggrcoef;
12868 newnvars++;
12869 }
12870 }
12871 }
12872 else
12873 {
12874 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12875#ifndef NDEBUG
12876 for( i = 0; i < nvarscommon; ++i )
12877 {
12878 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12879 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12880
12881 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12882 assert(SCIPisZero(scip, aggrcoef));
12883 }
12884#endif
12885 }
12886
12887 /* calculate the coefficients appearing in cons0 but not in cons1 */
12888 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12889 {
12890 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12891
12892 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12893 assert(!SCIPisZero(scip, aggrcoef));
12894 assert(newnvars < bestnvars);
12895 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12896 newvals[newnvars] = aggrcoef;
12897 newnvars++;
12898 }
12899
12900 /* calculate the coefficients appearing in cons1 but not in cons0 */
12901 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12902 {
12903 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12904
12905 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12906 assert(!SCIPisZero(scip, aggrcoef));
12907 assert(newnvars < bestnvars);
12908 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12909 newvals[newnvars] = aggrcoef;
12910 newnvars++;
12911 }
12912 assert(newnvars == bestnvars);
12913
12914 /* calculate the new left and right hand side of the (in)equality */
12915 assert(!SCIPisInfinity(scip, -consdata1->lhs));
12916 assert(!SCIPisInfinity(scip, consdata1->rhs));
12917 if( SCIPisInfinity(scip, -consdata0->lhs) )
12918 newlhs = -SCIPinfinity(scip);
12919 else
12920 newlhs = a * consdata0->lhs + b * consdata1->lhs;
12921 if( SCIPisInfinity(scip, consdata0->rhs) )
12922 newrhs = SCIPinfinity(scip);
12923 else
12924 newrhs = a * consdata0->rhs + b * consdata1->rhs;
12925
12926 /* create the new linear constraint */
12927 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12932
12933 newconsdata = SCIPconsGetData(newcons);
12934 assert(newconsdata != NULL);
12935
12936 /* copy the upgraded flag from the old cons0 to the new constraint */
12937 newconsdata->upgraded = consdata0->upgraded;
12938
12939 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12940
12941 if( *infeasible )
12942 goto TERMINATE;
12943
12944 /* check, if we really want to use the new constraint instead of the old one:
12945 * use the new one, if the maximum norm doesn't grow too much
12946 */
12947 if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12948 {
12949 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12950 SCIPdebugPrintCons(scip, newcons, NULL);
12951
12952 /* update the statistics: we changed all coefficients */
12953 if( !consdata0->upgraded )
12954 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12955 *aggregated = TRUE;
12956
12957 /* delete the old constraint, and add the new linear constraint to the problem */
12958 SCIP_CALL( SCIPdelCons(scip, cons0) );
12959 SCIP_CALL( SCIPaddCons(scip, newcons) );
12960 }
12961
12962 TERMINATE:
12963 /* release the new constraint */
12964 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12965
12966 /* free temporary memory */
12967 SCIPfreeBufferArray(scip, &newvals);
12968 SCIPfreeBufferArray(scip, &newvars);
12969 }
12970
12971 return SCIP_OKAY;
12972}
12973
12974/** gets the key of the given element */
12975static
12976SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12977{ /*lint --e{715}*/
12978 /* the key is the element itself */
12979 return elem;
12980}
12981
12982/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
12983 * coefficients are either equal or negated
12984 */
12985static
12986SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
12987{
12988 SCIP* scip;
12989 SCIP_CONSDATA* consdata1;
12990 SCIP_CONSDATA* consdata2;
12991 SCIP_Real minscale;
12992 SCIP_Real maxscale;
12993 int i;
12994
12995 assert(key1 != NULL);
12996 assert(key2 != NULL);
12997 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
12998 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
12999 assert(consdata1->indexsorted);
13000 assert(consdata2->indexsorted);
13001
13002 scip = (SCIP*)userptr;
13003 assert(scip != NULL);
13004
13005 /* if it is the same constraint we dont need to check anything */
13006 if( key1 == key2 )
13007 return TRUE;
13008
13009 /* checks trivial case */
13010 if( consdata1->nvars != consdata2->nvars )
13011 return FALSE;
13012
13013 /* tests if variables are equal */
13014 for( i = 0; i < consdata1->nvars; ++i )
13015 {
13016 if( consdata1->vars[i] != consdata2->vars[i] )
13017 {
13018 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13019 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13020 return FALSE;
13021 }
13022 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13023 }
13024
13025 /* order by maxabsval */
13026 if( consdataGetMaxAbsval(consdata1) > consdataGetMaxAbsval(consdata2) )
13027 SCIPswapPointers((void**)&consdata1, (void**)&consdata2);
13028
13029 /* initialize extremal scales */
13030 minscale = SCIPinfinity(scip);
13031 maxscale = -SCIPinfinity(scip);
13032
13033 /* test if coefficient scales are equal */
13034 for( i = 0; i < consdata1->nvars; ++i )
13035 {
13036 SCIP_Real scale = consdata2->vals[i] / consdata1->vals[i];
13037
13038 if( minscale > scale )
13039 {
13040 minscale = scale;
13041
13042 if( SCIPisLT(scip, minscale, maxscale) )
13043 return FALSE;
13044 }
13045
13046 if( maxscale < scale )
13047 {
13048 maxscale = scale;
13049
13050 if( SCIPisLT(scip, minscale, maxscale) )
13051 return FALSE;
13052 }
13053 }
13054
13055 return TRUE;
13056}
13057
13058/** returns the hash value of the key */
13059static
13060SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13061{
13062 SCIP_CONSDATA* consdata;
13063 int minidx;
13064 int mididx;
13065 int maxidx;
13066#ifndef NDEBUG
13067 SCIP* scip;
13068
13069 scip = (SCIP*)userptr;
13070 assert(scip != NULL);
13071#endif
13072
13073 assert(key != NULL);
13074 consdata = SCIPconsGetData((SCIP_CONS*)key);
13075 assert(consdata != NULL);
13076 assert(consdata->nvars > 0);
13077
13078 assert(consdata->indexsorted);
13079
13080 minidx = SCIPvarGetIndex(consdata->vars[0]);
13081 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13082 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13083
13084 /* using only the variable indices as hash, since the values are compared by epsilon */
13085 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
13086}
13087
13088/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13089 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13090 */
13091static
13093 SCIP_CONS* cons /**< linear constraint */
13094 )
13095{
13096 SCIP_CONSDATA* consdata;
13097
13098 assert(cons != NULL);
13099
13100 consdata = SCIPconsGetData(cons);
13101 assert(consdata != NULL);
13102
13103 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13104}
13105
13106/** updates the hashtable such that out of all constraints in the hashtable that are detected
13107 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13108 * and all others are removed from the hashtable and stored in the given array
13109 */
13110static
13112 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13113 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13114 * upon return will contain the constraint that should be kept */
13115 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13116 * these constraints where removed from the hashtable */
13117 int* nparallelconss /**< pointer to return number of parallel constraints */
13118 )
13119{
13120 SCIP_CONS* parallelcons;
13121 unsigned int querykey;
13122
13123 *nparallelconss = 0;
13124 querykey = getParallelConsKey(*querycons);
13125
13126 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13127 {
13128 unsigned int conskey = getParallelConsKey(parallelcons);
13129
13130 if( conskey < querykey )
13131 {
13132 parallelconss[(*nparallelconss)++] = *querycons;
13133 *querycons = parallelcons;
13134 querykey = conskey;
13135 }
13136 else
13137 {
13138 parallelconss[(*nparallelconss)++] = parallelcons;
13139 }
13140
13141 /* if the constraint that just came out of the hash table is the one that is kept,
13142 * we do not need to look into the hashtable again, since the invariant is that
13143 * in the hashtable only pair-wise non-parallel constraints are contained.
13144 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13145 * could be contained due to non-transitivity of the equality comparison.
13146 * Also we can return immediately, since parallelcons is already contained in the
13147 * hashtable and we do not need to remove and reinsert it.
13148 */
13149 if( *querycons == parallelcons )
13150 return SCIP_OKAY;
13151
13152 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13153 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13154 }
13155
13156 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13157 * comnpares equal to querycons at this point
13158 */
13159#ifndef NDEBUG
13160 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13161#else
13162 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13163#endif
13164
13165 return SCIP_OKAY;
13166}
13167
13168/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13169 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13170 */
13171static
13173 SCIP* scip, /**< SCIP data structure */
13174 BMS_BLKMEM* blkmem, /**< block memory */
13175 SCIP_CONS** conss, /**< constraint set */
13176 int nconss, /**< number of constraints in constraint set */
13177 int* firstchange, /**< pointer to store first changed constraint */
13178 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13179 int* ndelconss, /**< pointer to count number of deleted constraints */
13180 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13181 )
13182{
13183 SCIP_HASHTABLE* hashtable;
13184 SCIP_CONS** parallelconss;
13185 int nparallelconss;
13186 int hashtablesize;
13187 int c;
13188
13189 assert(scip != NULL);
13190 assert(blkmem != NULL);
13191 assert(conss != NULL);
13192 assert(firstchange != NULL);
13193 assert(cutoff != NULL);
13194 assert(ndelconss != NULL);
13195 assert(nchgsides != NULL);
13196
13197 /* create a hash table for the constraint set */
13198 hashtablesize = nconss;
13199 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13200 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13201
13202 SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13203
13204 /* check all constraints in the given set for redundancy */
13205 for( c = 0; c < nconss; ++c )
13206 {
13207 SCIP_CONS* cons0;
13208 SCIP_CONSDATA* consdata0;
13209
13210 cons0 = conss[c];
13211
13212 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13213 continue;
13214
13215 /* do not check for parallel constraints if they should not be upgraded */
13216 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13217 continue;
13218
13219 /* check for interuption */
13220 if( c % 1000 == 0 && SCIPisStopped(scip) )
13221 break;
13222
13223 /* sorts the constraint */
13224 consdata0 = SCIPconsGetData(cons0);
13225 assert(consdata0 != NULL);
13226 SCIP_CALL( consdataSort(scip, consdata0) );
13227 assert(consdata0->indexsorted);
13228
13229 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13230 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13231 * first variable is positive
13232 * Also inserts cons0 into the hashtable.
13233 */
13234 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13235
13236 if( nparallelconss != 0 )
13237 {
13238 SCIP_Real lhs;
13239 SCIP_Real rhs;
13240
13241 int i;
13242
13243 /* cons0 may have been changed in retrieveParallelConstraints() */
13244 consdata0 = SCIPconsGetData(cons0);
13245
13246 lhs = consdata0->lhs;
13247 rhs = consdata0->rhs;
13248
13249 for( i = 0; i < nparallelconss; ++i )
13250 {
13251 SCIP_CONS* consdel;
13252 SCIP_CONSDATA* consdatadel;
13253 SCIP_Real scale;
13254
13255 consdel = parallelconss[i];
13256 consdatadel = SCIPconsGetData(consdel);
13257
13258 /* do not delete constraint if it should not be upgraded */
13259 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13260 continue;
13261
13262 assert(SCIPconsIsActive(consdel));
13263 assert(!SCIPconsIsModifiable(consdel));
13264
13265 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13266 * delete old constraints afterwards
13267 */
13268 assert(consdatadel != NULL);
13269 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13270
13271 assert(consdatadel->indexsorted);
13272 assert(consdata0->vars[0] == consdatadel->vars[0]);
13273
13274 scale = consdata0->vals[0] / consdatadel->vals[0];
13275 assert(scale != 0.0);
13276
13277 /* in debug mode, check that all coefficients are equal with respect to epsilon
13278 * if the constraints are in equilibrium scale
13279 */
13280#ifndef NDEBUG
13281 {
13282 assert(consdata0->validmaxabsval);
13283 assert(consdatadel->validmaxabsval);
13284 int k;
13285 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13286 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13287
13288 for( k = 0; k < consdata0->nvars; ++k )
13289 {
13290 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13291 }
13292 }
13293#endif
13294
13295 if( scale > 0.0 )
13296 {
13297 /* the coefficients of both constraints are parallel with a positive scale */
13298 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13299 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13300 SCIPdebugPrintCons(scip, cons0, NULL);
13301 SCIPdebugPrintCons(scip, consdel, NULL);
13302
13303 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13304 lhs = MAX(scale * consdatadel->lhs, lhs);
13305
13306 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13307 rhs = MIN(scale * consdatadel->rhs, rhs);
13308 }
13309 else
13310 {
13311 /* the coefficients of both rows are negations */
13312 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13313 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13314 SCIPdebugPrintCons(scip, cons0, NULL);
13315 SCIPdebugPrintCons(scip, consdel, NULL);
13316
13317 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13318 lhs = MAX(scale * consdatadel->rhs, lhs);
13319
13320 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13321 rhs = MIN(scale * consdatadel->lhs, rhs);
13322 }
13323
13324 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13325 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13326
13327 /* delete consdel */
13328 assert( ! consdata0->upgraded || consdatadel->upgraded );
13329 SCIP_CALL( SCIPdelCons(scip, consdel) );
13330 if( !consdatadel->upgraded )
13331 (*ndelconss)++;
13332 }
13333
13334 if( SCIPisFeasLT(scip, rhs, lhs) )
13335 {
13336 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13337 *cutoff = TRUE;
13338 break;
13339 }
13340
13341 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13342 if( lhs > rhs )
13343 {
13344 rhs = (lhs + rhs)/2;
13345 lhs = rhs;
13346 }
13347
13348 /* update lhs and rhs of cons0 */
13349 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13350 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13351
13352 /* update the first changed constraint to begin the next aggregation round with */
13353 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13354 *firstchange = SCIPconsGetPos(cons0);
13355
13356 assert(SCIPconsIsActive(cons0));
13357 }
13358 }
13359#ifdef SCIP_MORE_DEBUG
13360 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13362#endif
13363
13364 SCIPfreeBufferArray(scip, &parallelconss);
13365
13366 /* free hash table */
13367 SCIPhashtableFree(&hashtable);
13368
13369 return SCIP_OKAY;
13370}
13371
13372/** compares constraint with all prior constraints for possible redundancy or aggregation,
13373 * and removes or changes constraint accordingly
13374 */
13375static
13377 SCIP* scip, /**< SCIP data structure */
13378 SCIP_CONS** conss, /**< constraint set */
13379 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13380 int chkind, /**< index of constraint to check against all prior indices upto startind */
13381 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13382 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13383 int* ndelconss, /**< pointer to count number of deleted constraints */
13384 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13385 int* nchgcoefs /**< pointer to count number of changed coefficients */
13386 )
13387{
13388 SCIP_CONS* cons0;
13389 SCIP_CONSDATA* consdata0;
13390 int* commonidx0;
13391 int* commonidx1;
13392 int* diffidx0minus1;
13393 int* diffidx1minus0;
13394 uint64_t possignature0;
13395 uint64_t negsignature0;
13396 SCIP_Bool cons0changed;
13397 SCIP_Bool cons0isequality;
13398 int diffidx1minus0size;
13399 int c;
13400 SCIP_Real cons0lhs;
13401 SCIP_Real cons0rhs;
13402 SCIP_Bool cons0upgraded;
13403
13404 assert(scip != NULL);
13405 assert(conss != NULL);
13406 assert(firstchange <= chkind);
13407 assert(cutoff != NULL);
13408 assert(ndelconss != NULL);
13409 assert(nchgsides != NULL);
13410 assert(nchgcoefs != NULL);
13411
13412 /* get the constraint to be checked against all prior constraints */
13413 cons0 = conss[chkind];
13414 assert(cons0 != NULL);
13415 assert(SCIPconsIsActive(cons0));
13416 assert(!SCIPconsIsModifiable(cons0));
13417
13418 consdata0 = SCIPconsGetData(cons0);
13419 assert(consdata0 != NULL);
13420 assert(consdata0->nvars >= 1);
13421 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13422
13423 /* sort the constraint */
13424 SCIP_CALL( consdataSort(scip, consdata0) );
13425
13426 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13427 consdataCalcSignatures(consdata0);
13428 possignature0 = consdata0->possignature;
13429 negsignature0 = consdata0->negsignature;
13430
13431 /* get temporary memory for indices of common variables */
13432 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13433 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13434 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13435 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13436 diffidx1minus0size = consdata0->nvars;
13437
13438 cons0lhs = consdata0->lhs;
13439 cons0rhs = consdata0->rhs;
13440 cons0upgraded = consdata0->upgraded;
13441
13442 /* check constraint against all prior constraints */
13443 cons0changed = consdata0->changed;
13444 consdata0->changed = FALSE;
13445 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13446 {
13447 SCIP_CONS* cons1;
13448 SCIP_CONSDATA* consdata1;
13449 uint64_t possignature1;
13450 uint64_t negsignature1;
13451 SCIP_Bool cons0dominateslhs;
13452 SCIP_Bool cons1dominateslhs;
13453 SCIP_Bool cons0dominatesrhs;
13454 SCIP_Bool cons1dominatesrhs;
13455 SCIP_Bool cons1isequality;
13456 SCIP_Bool coefsequal;
13457 SCIP_Bool coefsnegated;
13458 SCIP_Bool tryaggregation;
13459 int nvarscommon;
13460 int nvars0minus1;
13461 int nvars1minus0;
13462 int commonidxweight;
13463 int diffidx0minus1weight;
13464 int diffidx1minus0weight;
13465 int v0;
13466 int v1;
13467
13468 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13469 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13470 assert(cons0upgraded == consdata0->upgraded);
13471
13472 cons1 = conss[c];
13473
13474 /* cons1 has become inactive during presolving of constraint pairs */
13475 if( cons1 == NULL )
13476 continue;
13477
13478 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13479 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13480
13481 consdata1 = SCIPconsGetData(cons1);
13482 assert(consdata1 != NULL);
13483
13484 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13485 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13486 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13487
13488 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13489 if( !cons0changed && !consdata1->changed )
13490 continue;
13491
13492 /* if both constraints are already upgraded, skip the pair;
13493 * because changes on these constraints cannot be applied to the instance anymore */
13494 if( cons0upgraded && consdata1->upgraded )
13495 continue;
13496
13497 assert(consdata1->nvars >= 1);
13498
13499 /* sort the constraint */
13500 SCIP_CALL( consdataSort(scip, consdata1) );
13501
13502 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13503 consdataCalcSignatures(consdata1);
13504 possignature1 = consdata1->possignature;
13505 negsignature1 = consdata1->negsignature;
13506
13507 /* the signatures give a quick test to check for domination and equality of coefficients */
13508 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13509 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13510 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13511 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13512 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13513 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13514 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13515 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13516 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13517 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13518 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13519 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13520 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13521 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13522 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13523 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13524 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13525 && !coefsequal && !coefsnegated && !tryaggregation )
13526 continue;
13527
13528 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13529 if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13530 {
13531 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13532 diffidx1minus0size = consdata1->nvars;
13533 }
13534
13535 /* check consdata0 against consdata1:
13536 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13537 * consdata0 dominates consdata1 w.r.t. left hand side
13538 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13539 * consdata0 dominates consdata1 w.r.t. right hand side
13540 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13541 * ranged row (or equality)
13542 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13543 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13544 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13545 * number of continuous and integer variables are preferred:
13546 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13547 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13548 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13549 * to be positive to not switch the sense of the (in)equality cons0
13550 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13551 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13552 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13553 * to be positive to not switch the sense of the (in)equality cons1
13554 */
13555
13556 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13557 nvarscommon = 0;
13558 commonidxweight = 0;
13559 nvars0minus1 = 0;
13560 diffidx0minus1weight = 0;
13561 nvars1minus0 = 0;
13562 diffidx1minus0weight = 0;
13563 v0 = 0;
13564 v1 = 0;
13565 while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13566 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13567 || coefsequal || coefsnegated || tryaggregation) )
13568 {
13569 SCIP_VAR* var;
13570 SCIP_Real val0;
13571 SCIP_Real val1;
13572 int varcmp;
13573
13574 /* test, if variable appears in only one or in both constraints */
13575 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13576 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13577 else if( v0 < consdata0->nvars )
13578 varcmp = -1;
13579 else
13580 varcmp = +1;
13581
13582 switch( varcmp )
13583 {
13584 case -1:
13585 /* variable doesn't appear in consdata1 */
13586 var = consdata0->vars[v0];
13587 val0 = consdata0->vals[v0];
13588 val1 = 0.0;
13589 if( tryaggregation )
13590 {
13591 diffidx0minus1[nvars0minus1] = v0;
13592 nvars0minus1++;
13593 diffidx0minus1weight += getVarWeight(var);
13594 }
13595 v0++;
13596 coefsequal = FALSE;
13597 coefsnegated = FALSE;
13598 break;
13599
13600 case +1:
13601 /* variable doesn't appear in consdata0 */
13602 var = consdata1->vars[v1];
13603 val0 = 0.0;
13604 val1 = consdata1->vals[v1];
13605 if( tryaggregation )
13606 {
13607 diffidx1minus0[nvars1minus0] = v1;
13608 nvars1minus0++;
13609 diffidx1minus0weight += getVarWeight(var);
13610 }
13611 v1++;
13612 coefsequal = FALSE;
13613 coefsnegated = FALSE;
13614 break;
13615
13616 case 0:
13617 /* variable appears in both constraints */
13618 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13619 var = consdata0->vars[v0];
13620 val0 = consdata0->vals[v0];
13621 val1 = consdata1->vals[v1];
13622 if( tryaggregation )
13623 {
13624 commonidx0[nvarscommon] = v0;
13625 commonidx1[nvarscommon] = v1;
13626 nvarscommon++;
13627 commonidxweight += getVarWeight(var);
13628 }
13629 v0++;
13630 v1++;
13631 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13632 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13633 break;
13634
13635 default:
13636 SCIPerrorMessage("invalid comparison result\n");
13637 SCIPABORT();
13638 var = NULL;
13639 val0 = 0.0;
13640 val1 = 0.0;
13641 }
13642 assert(var != NULL);
13643
13644 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13645 if( SCIPisGT(scip, val0, val1) )
13646 {
13648 {
13649 cons0dominatesrhs = FALSE;
13650 cons1dominateslhs = FALSE;
13651 }
13653 {
13654 cons0dominateslhs = FALSE;
13655 cons1dominatesrhs = FALSE;
13656 }
13657 }
13658 else if( SCIPisLT(scip, val0, val1) )
13659 {
13661 {
13662 cons0dominateslhs = FALSE;
13663 cons1dominatesrhs = FALSE;
13664 }
13666 {
13667 cons0dominatesrhs = FALSE;
13668 cons1dominateslhs = FALSE;
13669 }
13670 }
13671 }
13672
13673 /* check for disaggregated ranged rows */
13674 if( coefsequal || coefsnegated )
13675 {
13676 SCIP_CONS* consstay;
13677 SCIP_CONS* consdel;
13678#ifndef NDEBUG
13679 SCIP_CONSDATA* consdatastay;
13680#endif
13681 SCIP_CONSDATA* consdatadel;
13682 SCIP_Real lhs;
13683 SCIP_Real rhs;
13684 int consinddel;
13685
13686 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13687 * best left and right hand sides; delete the old constraints afterwards
13688 */
13689 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13690 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13691 SCIPdebugPrintCons(scip, cons0, NULL);
13692 SCIPdebugPrintCons(scip, cons1, NULL);
13693
13694 if( coefsequal )
13695 {
13696 /* the coefficients of both rows are equal */
13697 lhs = MAX(consdata0->lhs, consdata1->lhs);
13698 rhs = MIN(consdata0->rhs, consdata1->rhs);
13699 }
13700 else
13701 {
13702 /* the coefficients of both rows are negations */
13703 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13704 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13705 }
13706 if( SCIPisFeasLT(scip, rhs, lhs) )
13707 {
13708 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13709 *cutoff = TRUE;
13710 break;
13711 }
13712
13713 /* check which constraint has to stay;
13714 * changes applied to an upgraded constraint will not be considered in the instance */
13715 if( consdata0->upgraded )
13716 {
13717 assert(!consdata1->upgraded);
13718 consstay = cons1;
13719#ifndef NDEBUG
13720 consdatastay = consdata1;
13721#endif
13722
13723 consdel = cons0;
13724 consdatadel = consdata0;
13725 consinddel = chkind;
13726 }
13727 else
13728 {
13729 consstay = cons0;
13730#ifndef NDEBUG
13731 consdatastay = consdata0;
13732#endif
13733
13734 consdel = cons1;
13735 consdatadel = consdata1;
13736 consinddel = c;
13737 }
13738
13739 /* update the sides of consstay */
13740 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13741 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13742 if( !consdata0->upgraded )
13743 {
13744 assert(consstay == cons0);
13745 cons0lhs = consdata0->lhs;
13746 cons0rhs = consdata0->rhs;
13747 }
13748
13749 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13750 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13751
13752 assert( !consdatastay->upgraded );
13753 /* delete consdel */
13754 SCIP_CALL( SCIPdelCons(scip, consdel) );
13755 conss[consinddel] = NULL;
13756 if( !consdatadel->upgraded )
13757 (*ndelconss)++;
13758 continue;
13759 }
13760
13761 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13762 * redundant
13763 */
13764 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13765 {
13766 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13767 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13768 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13769 SCIPdebugPrintCons(scip, cons0, NULL);
13770 SCIPdebugPrintCons(scip, cons1, NULL);
13771
13772 /* check for infeasibility */
13773 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13774 {
13775 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13776 *cutoff = TRUE;
13777 break;
13778 }
13779
13780 /* remove redundant left hand side */
13781 if( !SCIPisInfinity(scip, -consdata0->lhs) )
13782 {
13783 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13784 cons0lhs = consdata0->lhs;
13785 cons0isequality = FALSE;
13786 if( !consdata0->upgraded )
13787 {
13788 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13789 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13790
13791 (*nchgsides)++;
13792 }
13793 }
13794 }
13795 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13796 {
13797 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13798 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13799 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13800 SCIPdebugPrintCons(scip, cons1, NULL);
13801 SCIPdebugPrintCons(scip, cons0, NULL);
13802
13803 /* check for infeasibility */
13804 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13805 {
13806 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13807 *cutoff = TRUE;
13808 break;
13809 }
13810
13811 /* remove redundant left hand side */
13812 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13813 {
13814 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13815 cons1isequality = FALSE;
13816 if( !consdata1->upgraded )
13817 {
13818 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13819 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13820
13821 (*nchgsides)++;
13822 }
13823 }
13824 }
13825 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13826 {
13827 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13828 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13829 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13830 SCIPdebugPrintCons(scip, cons0, NULL);
13831 SCIPdebugPrintCons(scip, cons1, NULL);
13832
13833 /* check for infeasibility */
13834 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13835 {
13836 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13837 *cutoff = TRUE;
13838 break;
13839 }
13840
13841 /* remove redundant right hand side */
13842 if( !SCIPisInfinity(scip, consdata0->rhs) )
13843 {
13844 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13845 cons0rhs = consdata0->rhs;
13846 cons0isequality = FALSE;
13847 if( !consdata0->upgraded )
13848 {
13849 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13850 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13851
13852 (*nchgsides)++;
13853 }
13854 }
13855 }
13856 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13857 {
13858 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13859 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13860 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13861 SCIPdebugPrintCons(scip, cons1, NULL);
13862 SCIPdebugPrintCons(scip, cons0, NULL);
13863
13864 /* check for infeasibility */
13865 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13866 {
13867 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13868 *cutoff = TRUE;
13869 break;
13870 }
13871
13872 /* remove redundant right hand side */
13873 if( !SCIPisInfinity(scip, consdata1->rhs) )
13874 {
13875 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13876 cons1isequality = FALSE;
13877 if( !consdata1->upgraded )
13878 {
13879 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13880 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13881
13882 (*nchgsides)++;
13883 }
13884 }
13885 }
13886
13887 /* check for now redundant constraints */
13888 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13889 {
13890 /* consdata0 became redundant */
13891 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13892 SCIP_CALL( SCIPdelCons(scip, cons0) );
13893 conss[chkind] = NULL;
13894 if( !consdata0->upgraded )
13895 {
13896 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13897 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13898
13899 (*ndelconss)++;
13900 }
13901 continue;
13902 }
13903 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13904 {
13905 /* consdata1 became redundant */
13906 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13907 SCIP_CALL( SCIPdelCons(scip, cons1) );
13908 conss[c] = NULL;
13909 if( !consdata1->upgraded )
13910 {
13911 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13912 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13913
13914 (*ndelconss)++;
13915 }
13916 continue;
13917 }
13918
13919 /* check, if we want to aggregate an (in)equality with an equality:
13920 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13921 */
13922 if( tryaggregation )
13923 {
13924 SCIP_Bool aggregated;
13925
13926 assert(consdata0->nvars == nvarscommon + nvars0minus1);
13927 assert(consdata1->nvars == nvarscommon + nvars1minus0);
13928
13929 aggregated = FALSE;
13930 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13931 {
13932 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13933 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13934 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13935 nchgcoefs, &aggregated, cutoff) );
13936
13937 if( *cutoff )
13938 break;
13939
13940 /* update array of active constraints */
13941 if( aggregated )
13942 {
13943 assert(!SCIPconsIsActive(cons0));
13944 assert(SCIPconsIsActive(cons1));
13945 conss[chkind] = NULL;
13946 }
13947 }
13948 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13949 {
13950 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13951 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13952 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13953 nchgcoefs, &aggregated, cutoff) );
13954
13955 if( *cutoff )
13956 break;
13957
13958 /* update array of active constraints */
13959 if( aggregated )
13960 {
13961 assert(!SCIPconsIsActive(cons1));
13962 assert(SCIPconsIsActive(cons0));
13963 conss[c] = NULL;
13964 }
13965 }
13966 }
13967 }
13968
13969 /* free temporary memory */
13970 SCIPfreeBufferArray(scip, &diffidx1minus0);
13971 SCIPfreeBufferArray(scip, &diffidx0minus1);
13972 SCIPfreeBufferArray(scip, &commonidx1);
13973 SCIPfreeBufferArray(scip, &commonidx0);
13974
13975 return SCIP_OKAY;
13976}
13977
13978/** do stuffing presolving on a single constraint */
13979static
13981 SCIP* scip, /**< SCIP data structure */
13982 SCIP_CONS* cons, /**< linear constraint */
13983 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
13984 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
13985 * constraints using the cheapest variable? */
13986 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13987 int* nfixedvars, /**< pointer to count the total number of fixed variables */
13988 int* nchgbds /**< pointer to count the total number of tightened bounds */
13989 )
13990{
13991 SCIP_CONSDATA* consdata;
13992 SCIP_Real* ratios;
13993 int* varpos;
13994 SCIP_Bool* swapped;
13995 SCIP_VAR** vars;
13996 SCIP_Real* vals;
13997 SCIP_VAR* var;
13998 SCIP_Real lb;
13999 SCIP_Real ub;
14000 SCIP_Real minactivity;
14001 SCIP_Real maxactivity;
14002 SCIP_Real maxcondactivity;
14003 SCIP_Real mincondactivity;
14004 SCIP_Real rhs;
14005 SCIP_Real val;
14006 SCIP_Real obj;
14007 SCIP_Real factor;
14008 SCIP_Bool isminacttight;
14009 SCIP_Bool ismaxacttight;
14010 SCIP_Bool isminsettoinfinity;
14011 SCIP_Bool ismaxsettoinfinity;
14012 SCIP_Bool tryfixing;
14013 int nsingletons;
14014 int idx;
14015 int v;
14016 int nvars;
14017
14018 assert(scip != NULL);
14019 assert(cons != NULL);
14020 assert(nfixedvars != NULL);
14021
14022 consdata = SCIPconsGetData(cons);
14023
14024 /* we only want to run for inequalities */
14025 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14026 return SCIP_OKAY;
14027
14028 if( singlevarstuffing )
14029 {
14030 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
14031 &isminsettoinfinity, &ismaxsettoinfinity);
14032 }
14033 else
14034 {
14035 minactivity = SCIP_INVALID;
14036 maxactivity = SCIP_INVALID;
14037 isminsettoinfinity = FALSE;
14038 ismaxsettoinfinity = FALSE;
14039 }
14040
14041 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14042 * the new maxactivity is minus the old minactivity then
14043 */
14044 if( SCIPisInfinity(scip, consdata->rhs) )
14045 {
14046 rhs = -consdata->lhs;
14047 factor = -1.0;
14048 maxactivity = -minactivity;
14049 ismaxsettoinfinity = isminsettoinfinity;
14050 }
14051 else
14052 {
14053 assert(SCIPisInfinity(scip, -consdata->lhs));
14054 rhs = consdata->rhs;
14055 factor = 1.0;
14056 }
14057
14058 nvars = consdata->nvars;
14059 vars = consdata->vars;
14060 vals = consdata->vals;
14061
14062 /* check for continuous singletons */
14063 if( singletonstuffing )
14064 {
14065 for( v = 0; v < nvars; ++v )
14066 {
14067 var = vars[v];
14068
14071 break;
14072 }
14073 }
14074 else
14075 /* we don't want to go into the next block */
14076 v = nvars;
14077
14078 /* a singleton was found -> perform singleton variable stuffing */
14079 if( v < nvars )
14080 {
14081 assert(singletonstuffing);
14082
14083 SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14084 SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14085 SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14086
14087 tryfixing = TRUE;
14088 nsingletons = 0;
14089 mincondactivity = 0.0;
14090 maxcondactivity = 0.0;
14091
14092 for( v = 0; v < nvars; ++v )
14093 {
14094 var = vars[v];
14095 lb = SCIPvarGetLbGlobal(var);
14096 ub = SCIPvarGetUbGlobal(var);
14097 obj = SCIPvarGetObj(var);
14098 val = factor * vals[v];
14099
14100 assert(!SCIPisZero(scip, val));
14101
14102 /* the variable is a singleton and continuous */
14105 {
14106 if( SCIPisNegative(scip, obj) && val > 0 )
14107 {
14108 /* case 1: obj < 0 and coef > 0 */
14109 if( SCIPisInfinity(scip, -lb) )
14110 {
14111 tryfixing = FALSE;
14112 break;
14113 }
14114
14115 maxcondactivity += val * lb;
14116 mincondactivity += val * lb;
14117 swapped[v] = FALSE;
14118 ratios[nsingletons] = obj / val;
14119 varpos[nsingletons] = v;
14120 nsingletons++;
14121 }
14122 else if( SCIPisPositive(scip, obj) && val < 0 )
14123 {
14124 /* case 2: obj > 0 and coef < 0 */
14125 if( SCIPisInfinity(scip, ub) )
14126 {
14127 tryfixing = FALSE;
14128 break;
14129 }
14130 /* multiply column by (-1) to become case 1.
14131 * now bounds are swapped: ub := -lb, lb := -ub
14132 */
14133
14134 maxcondactivity += val * ub;
14135 mincondactivity += val * ub;
14136 swapped[v] = TRUE;
14137 ratios[nsingletons] = obj / val;
14138 varpos[nsingletons] = v;
14139 nsingletons++;
14140 }
14141 else if( val > 0 )
14142 {
14143 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14144 * we only consider the lower bound for the constants
14145 */
14146 assert(!SCIPisNegative(scip, obj));
14147
14148 if( SCIPisInfinity(scip, -lb) )
14149 {
14150 /* maybe unbounded */
14151 tryfixing = FALSE;
14152 break;
14153 }
14154
14155 maxcondactivity += val * lb;
14156 mincondactivity += val * lb;
14157 }
14158 else
14159 {
14160 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14161 * we only consider the upper bound for the constants
14162 */
14163 assert(!SCIPisPositive(scip, obj));
14164 assert(val < 0);
14165
14166 if( SCIPisInfinity(scip, ub) )
14167 {
14168 /* maybe unbounded */
14169 tryfixing = FALSE;
14170 break;
14171 }
14172
14173 maxcondactivity += val * ub;
14174 mincondactivity += val * ub;
14175 }
14176 }
14177 else
14178 {
14179 /* consider contribution of discrete variables, non-singleton
14180 * continuous variables and variables with more than one lock
14181 */
14182 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14183 {
14184 tryfixing = FALSE;
14185 break;
14186 }
14187
14188 if( val > 0 )
14189 {
14190 maxcondactivity += val * ub;
14191 mincondactivity += val * lb;
14192 }
14193 else
14194 {
14195 maxcondactivity += val * lb;
14196 mincondactivity += val * ub;
14197 }
14198 }
14199 }
14200 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14201 {
14202 SCIP_Real delta;
14203 SCIP_Bool tightened;
14204#ifdef SCIP_DEBUG
14205 int oldnfixedvars = *nfixedvars;
14206#endif
14207
14208 SCIPsortRealInt(ratios, varpos, nsingletons);
14209
14210 /* verify which singleton continuous variables can be fixed */
14211 for( v = 0; v < nsingletons; ++v )
14212 {
14213 idx = varpos[v];
14214 var = vars[idx];
14215 val = factor * vals[idx];
14216 lb = SCIPvarGetLbGlobal(var);
14217 ub = SCIPvarGetUbGlobal(var);
14218
14219 assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14220 assert((val < 0) == swapped[idx]);
14221 val = REALABS(val);
14222
14223 /* stop fixing if variable bounds are not finite */
14224 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14225 break;
14226
14230
14231 /* calculate the change in the row activities if this variable changes
14232 * its value from its worst to its best bound
14233 */
14234 if( swapped[idx] )
14235 delta = -(lb - ub) * val;
14236 else
14237 delta = (ub - lb) * val;
14238
14239 assert(!SCIPisNegative(scip, delta));
14240
14241 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14242 {
14243 if( swapped[idx] )
14244 {
14245 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14246 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14247 }
14248 else
14249 {
14250 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14251 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14252 }
14253
14254 if( *cutoff )
14255 break;
14256 if( tightened )
14257 {
14258 (*nfixedvars)++;
14259 }
14260 }
14261 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14262 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14263 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14264 * troubles in case of large bounds.
14265 */
14266 else if( SCIPisLE(scip, rhs, mincondactivity) )
14267 {
14268 if( swapped[idx] )
14269 {
14270 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14271 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14272 }
14273 else
14274 {
14275 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14276 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14277 }
14278
14279 if( *cutoff )
14280 break;
14281 if( tightened )
14282 {
14283 (*nfixedvars)++;
14284 }
14285 }
14286
14287 maxcondactivity += delta;
14288 mincondactivity += delta;
14289 }
14290
14291#ifdef SCIP_DEBUG
14292 if( *nfixedvars - oldnfixedvars > 0 )
14293 {
14294 SCIPdebugMsg(scip, "### stuffing fixed %d variables\n", *nfixedvars - oldnfixedvars);
14295 }
14296#endif
14297 }
14298
14299 SCIPfreeBufferArray(scip, &swapped);
14300 SCIPfreeBufferArray(scip, &ratios);
14301 SCIPfreeBufferArray(scip, &varpos);
14302 }
14303
14304 /* perform single-variable stuffing:
14305 * for a linear inequality
14306 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14307 * with a_i > 0 and objective coefficients c_i < 0,
14308 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14309 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14310 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14311 * is redundant.
14312 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14313 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14314 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14315 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14316 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14317 * upper bound.
14318 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14319 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14320 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14321 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14322 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14323 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14324 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14325 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14326 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14327 * c_k * ceil((maxactivity - rhs)/val) is still better than
14328 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14329 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14330 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14331 * sign of coefficients in constraint and objective prevent the use of this method.
14332 */
14333 if( singlevarstuffing && !ismaxsettoinfinity )
14334 {
14335 SCIP_Real bestratio = -SCIPinfinity(scip);
14336 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14337 SCIP_Real ratio;
14338 int bestindex = -1;
14339 int bestuplocks = 0;
14340 int bestdownlocks = 1;
14341 int downlocks;
14342 int uplocks;
14343 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14344 SCIPdebug( int oldnchgbds = *nchgbds; )
14345
14346 /* loop over all variables to identify the best and second-best ratio */
14347 for( v = 0; v < nvars; ++v )
14348 {
14349 var = vars[v];
14350 obj = SCIPvarGetObj(var);
14351 val = factor * vals[v];
14352
14353 assert(!SCIPisZero(scip, val));
14354
14355 ratio = obj / val;
14356
14357 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14358 if( !SCIPisNegative(scip, ratio) )
14359 {
14360 bestindex = -1;
14361 break;
14362 }
14363
14364 if( val > 0 )
14365 {
14368 }
14369 else
14370 {
14373 }
14374
14375 /* better ratio, update best candidate
14376 * @todo use some tolerance
14377 * @todo check size of domain and updated ratio for integer variables already?
14378 */
14379 if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14380 || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14382 {
14383 /* best index becomes second-best*/
14384 if( bestindex != -1 )
14385 {
14386 /* second-best index must not have more than 1 uplock */
14387 if( bestuplocks > 1 )
14388 {
14389 bestindex = -1;
14390 break;
14391 }
14392 else
14393 {
14394 secondbestratio = bestratio;
14395 }
14396 }
14397 bestdownlocks = downlocks;
14398 bestuplocks = uplocks;
14399 bestratio = ratio;
14400 bestindex = v;
14401
14402 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14403 * if it is not the best, it has too many uplocks -> not applicable
14404 */
14405 if( bestdownlocks > 0 && bestuplocks > 1 )
14406 {
14407 bestindex = -1;
14408 break;
14409 }
14410 }
14411 else
14412 {
14413 /* non-best index must not have more than 1 uplock */
14414 if( uplocks > 1 )
14415 {
14416 bestindex = -1;
14417 break;
14418 }
14419 /* update second-best ratio */
14420 if( ratio > secondbestratio )
14421 {
14422 secondbestratio = ratio;
14423 }
14424 }
14425 }
14426
14427 /* check if we can apply single variable stuffing */
14428 if( bestindex != -1 && bestdownlocks == 0 )
14429 {
14430 SCIP_Bool tightened = FALSE;
14431 SCIP_Real bounddelta;
14432
14433 var = vars[bestindex];
14434 obj = SCIPvarGetObj(var);
14435 val = factor * vals[bestindex];
14436 lb = SCIPvarGetLbGlobal(var);
14437 ub = SCIPvarGetUbGlobal(var);
14438 tryfixing = TRUE;
14439
14440 if( val < 0 )
14441 {
14442 assert(!SCIPisNegative(scip, obj));
14443
14444 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14445 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14446 {
14447 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14448 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14449 assert(SCIPisPositive(scip, activitydelta));
14450
14451 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14452
14453 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14454 assert(SCIPisPositive(scip, bounddelta));
14455 }
14456 else
14457 bounddelta = (maxactivity - rhs)/-val;
14458
14459 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14460
14461 if( tryfixing )
14462 {
14464
14465 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14466 {
14467 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14468 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14469 }
14470 else
14471 {
14472 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14473 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14474 }
14475 }
14476 }
14477 else
14478 {
14479 assert(!SCIPisPositive(scip, obj));
14480
14481 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14482 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14483 {
14484 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14485 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14486 assert(SCIPisPositive(scip, activitydelta));
14487
14488 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14489
14490 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14491 assert(SCIPisPositive(scip, bounddelta));
14492 }
14493 else
14494 bounddelta = (maxactivity - rhs)/val;
14495
14496 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14497
14498 if( tryfixing )
14499 {
14501
14502 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14503 {
14504 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14505 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14506 }
14507 else
14508 {
14509 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14510 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14511 }
14512 }
14513 }
14514
14515 if( *cutoff )
14516 return SCIP_OKAY;
14517 if( tightened )
14518 {
14520 ++(*nfixedvars);
14521 else
14522 ++(*nchgbds);
14523
14524 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14525 for( v = 0; v < nvars; ++v )
14526 {
14527 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14528 SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14531 SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14532 }
14533 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14534
14535 for( v = 0; v < nvars; ++v )
14536 {
14537 if( v == bestindex )
14538 continue;
14539
14540 if( factor * vals[v] < 0 )
14541 {
14542 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14543 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14544 SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14545 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14546 }
14547 else
14548 {
14549 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14550 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14551 SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14552 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14553 }
14554
14555 if( *cutoff )
14556 return SCIP_OKAY;
14557 if( tightened )
14558 ++(*nfixedvars);
14559 }
14560 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14561 }
14562 }
14563 }
14564
14565 return SCIP_OKAY;
14566}
14567
14568/** applies full dual presolving on variables that only appear in linear constraints */
14569static
14571 SCIP* scip, /**< SCIP data structure */
14572 SCIP_CONS** conss, /**< constraint set */
14573 int nconss, /**< number of constraints */
14574 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14575 int* nchgbds, /**< pointer to count the number of bound changes */
14576 int* nchgvartypes /**< pointer to count the number of variable type changes */
14577 )
14578{
14579 SCIP_Real* redlb;
14580 SCIP_Real* redub;
14581 int* nlocksdown;
14582 int* nlocksup;
14583 SCIP_Bool* isimplint;
14584 SCIP_VAR** origvars;
14585 SCIP_VAR** vars;
14586 SCIP_VAR** conscontvars;
14587 int nvars;
14588 int nbinvars;
14589 int nintvars;
14590 int ncontvars;
14591 int v;
14592 int c;
14593
14594 /* we calculate redundancy bounds with the following meaning:
14595 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14596 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14597 * then:
14598 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14599 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14600 */
14601
14602 /* Additionally, we detect continuous variables that are implicitly integral.
14603 * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14604 * and all constraints (including the bounds as trivial constraints) in which:
14605 * c_j > 0: the variable is down-locked,
14606 * c_j < 0: the variable is up-locked,
14607 * c_j = 0: the variable appears
14608 * have, apart from j, only integer variables with integral coefficients and integral sides.
14609 * This is because then, the value of the variable is either determined by one of its bounds or
14610 * by one of these constraints, and in all cases, the value of the variable is integral.
14611 */
14612
14613 assert(scip != NULL);
14614 assert(nconss == 0 || conss != NULL);
14615 assert(nchgbds != NULL);
14616 assert(!SCIPinProbing(scip));
14617
14618 /* get active variables */
14619 nvars = SCIPgetNVars(scip);
14620 origvars = SCIPgetVars(scip);
14621
14622 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14623 nbinvars = SCIPgetNBinVars(scip);
14624 if( nbinvars == nvars )
14625 return SCIP_OKAY;
14626
14627 /* get number of continuous variables */
14628 ncontvars = SCIPgetNContVars(scip);
14629 nintvars = nvars - ncontvars;
14630
14631 /* copy the variable array since this array might change during the curse of this algorithm */
14632 nvars = nvars - nbinvars;
14633 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14634
14635 /* allocate temporary memory */
14636 SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14637 SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14638 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14639 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14640 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14641 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14642
14643 /* initialize redundancy bounds */
14644 for( v = 0; v < nvars; ++v )
14645 {
14646 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14647 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14648 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14649 }
14650 BMSclearMemoryArray(nlocksdown, nvars);
14651 BMSclearMemoryArray(nlocksup, nvars);
14652
14653 /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14654 * We better not use SCIPisFeasIntegral() in these checks.
14655 */
14656 for( v = 0; v < ncontvars; v++ )
14657 {
14658 SCIP_VAR* var;
14659 SCIP_Real obj;
14660 SCIP_Real lb;
14661 SCIP_Real ub;
14662
14663 var = vars[v + nintvars - nbinvars];
14664 lb = SCIPvarGetLbGlobal(var);
14665 ub = SCIPvarGetUbGlobal(var);
14666
14667 obj = SCIPvarGetObj(var);
14668 if( SCIPisZero(scip, obj) )
14669 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14670 else
14671 {
14672 if( SCIPisPositive(scip, obj) )
14673 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14674 else
14675 {
14676 assert(SCIPisNegative(scip, obj));
14677 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14678 }
14679 }
14680 }
14681
14682 /* scan all constraints */
14683 for( c = 0; c < nconss; ++c )
14684 {
14685 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14686 * part of checked disjunctions)
14687 */
14688 if( SCIPconsIsLocked(conss[c]) )
14689 {
14690 SCIP_CONSDATA* consdata;
14691 SCIP_Bool lhsexists;
14692 SCIP_Bool rhsexists;
14693 SCIP_Bool hasimpliedpotential;
14694 SCIP_Bool integralcoefs;
14695 int nlockspos;
14696 int contvarpos;
14697 int nconscontvars;
14698 int i;
14699
14700 consdata = SCIPconsGetData(conss[c]);
14701 assert(consdata != NULL);
14702
14703 /* get number of times the constraint was locked */
14704 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14705
14706 /* we do not want to include constraints with locked negation (this would be too weird) */
14707 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14708 {
14709 /* mark all continuous variables as not being implicit integral */
14710 for( i = 0; i < consdata->nvars; ++i )
14711 {
14712 SCIP_VAR* var;
14713
14714 var = consdata->vars[i];
14716 {
14717 int contv;
14718 contv = SCIPvarGetProbindex(var) - nintvars;
14719 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14720 isimplint[contv] = FALSE;
14721 }
14722 }
14723 continue;
14724 }
14725
14726 /* check for existing sides */
14727 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14728 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14729
14730 /* count locks and update redundancy bounds */
14731 contvarpos = -1;
14732 nconscontvars = 0;
14733 hasimpliedpotential = FALSE;
14734 integralcoefs = !SCIPconsIsModifiable(conss[c]);
14735
14736 for( i = 0; i < consdata->nvars; ++i )
14737 {
14738 SCIP_VAR* var;
14739 SCIP_Real val;
14740 SCIP_Real minresactivity;
14741 SCIP_Real maxresactivity;
14742 SCIP_Real newredlb;
14743 SCIP_Real newredub;
14744 SCIP_Bool ismintight;
14745 SCIP_Bool ismaxtight;
14746 SCIP_Bool isminsettoinfinity;
14747 SCIP_Bool ismaxsettoinfinity;
14748 int arrayindex;
14749
14750 var = consdata->vars[i];
14751 assert(var != NULL);
14752 val = consdata->vals[i];
14753 assert(!SCIPisZero(scip, val));
14754
14755 /* check if still all integer variables have integral coefficients */
14756 if( SCIPvarIsIntegral(var) )
14757 integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14758
14759 /* we do not need to process binary variables */
14760 if( SCIPvarIsBinary(var) )
14761 continue;
14762
14763 if( SCIPconsIsModifiable(conss[c]) )
14764 {
14765 minresactivity = -SCIPinfinity(scip);
14766 maxresactivity = SCIPinfinity(scip);
14767 isminsettoinfinity = TRUE;
14768 ismaxsettoinfinity = TRUE;
14769 }
14770 else
14771 {
14772 /* calculate residual activity bounds if variable would be fixed to zero */
14773 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14774 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
14775
14776 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14777 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14778 * This is needed, because we do not want to rely on relaxed finite resactivities.
14779 */
14780 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
14781
14782 /* check minresactivity for reliability */
14783 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14784 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14785
14786 /* check maxresactivity for reliability */
14787 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14788 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14789 }
14790
14791 arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14792
14793 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14794
14795 newredlb = redlb[arrayindex];
14796 newredub = redub[arrayindex];
14797 if( val > 0.0 )
14798 {
14799 if( lhsexists )
14800 {
14801 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14802 nlocksdown[arrayindex] += nlockspos;
14803 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14804 }
14805 if( rhsexists )
14806 {
14807 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14808 nlocksup[arrayindex] += nlockspos;
14809 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14810 }
14811 }
14812 else
14813 {
14814 if( lhsexists )
14815 {
14816 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14817 nlocksup[arrayindex] += nlockspos;
14818 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14819 }
14820 if( rhsexists )
14821 {
14822 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14823 nlocksdown[arrayindex] += nlockspos;
14824 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14825 }
14826 }
14827
14828 /* if the variable is integer, we have to round the value to the next integral value */
14829 if( SCIPvarIsIntegral(var) )
14830 {
14831 if( !SCIPisInfinity(scip, newredlb) )
14832 newredlb = SCIPceil(scip, newredlb);
14833 if( !SCIPisInfinity(scip, -newredub) )
14834 newredub = SCIPfloor(scip, newredub);
14835 }
14836
14837 /* update redundancy bounds */
14838 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14839 redub[arrayindex] = MIN(redub[arrayindex], newredub);
14840
14841 /* collect the continuous variables of the constraint */
14843 {
14844 int contv;
14845
14846 assert(nconscontvars < ncontvars);
14847 contvarpos = i;
14848 conscontvars[nconscontvars] = var;
14849 nconscontvars++;
14850
14851 contv = SCIPvarGetProbindex(var) - nintvars;
14852 assert(0 <= contv && contv < ncontvars);
14853 hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14854 }
14855 }
14856
14857 /* update implicit integer status of continuous variables */
14858 if( hasimpliedpotential )
14859 {
14860 if( nconscontvars > 1 || !integralcoefs )
14861 {
14862 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14863 * none of the continuous variables is implicit integer
14864 */
14865 for( i = 0; i < nconscontvars; i++ )
14866 {
14867 int contv;
14868 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14869 assert(0 <= contv && contv < ncontvars);
14870 isimplint[contv] = FALSE;
14871 }
14872 }
14873 else
14874 {
14875 SCIP_VAR* var;
14876 SCIP_Real val;
14877 SCIP_Real absval;
14878 int contv;
14879
14880 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14881 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14882 * side(s) of the constraint is integral
14883 */
14884 assert(nconscontvars == 1);
14885 assert(0 <= contvarpos && contvarpos < consdata->nvars);
14886 var = consdata->vars[contvarpos];
14887 val = consdata->vals[contvarpos];
14888 contv = SCIPvarGetProbindex(var) - nintvars;
14889 assert(0 <= contv && contv < ncontvars);
14890 assert(isimplint[contv]);
14891
14892 absval = REALABS(val);
14893 if( !SCIPisEQ(scip, absval, 1.0) )
14894 isimplint[contv] = FALSE;
14895 else
14896 {
14897 SCIP_Real obj;
14898
14899 obj = SCIPvarGetObj(var);
14900 if( obj * val >= 0.0 && lhsexists )
14901 {
14902 /* the variable may be blocked by the constraint's left hand side */
14903 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14904 }
14905 if( obj * val <= 0.0 && rhsexists )
14906 {
14907 /* the variable may be blocked by the constraint's left hand side */
14908 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14909 }
14910 }
14911 }
14912 }
14913 }
14914 }
14915
14916 /* check if any bounds can be tightened due to optimality */
14917 for( v = 0; v < nvars; ++v )
14918 {
14919 SCIP_VAR* var;
14920 SCIP_Real obj;
14921 SCIP_Bool infeasible;
14922 SCIP_Bool tightened;
14923
14924 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14925 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14926 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14927
14928 var = vars[v];
14929 obj = SCIPvarGetObj(var);
14930 if( !SCIPisPositive(scip, -obj) )
14931 {
14932 /* making the variable as small as possible does not increase the objective:
14933 * check if all down locks of the variables are due to linear constraints;
14934 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
14935 * constraints redundant is huge, we better do nothing for numerical reasons
14936 */
14938 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
14939 && !SCIPisHugeValue(scip, -redlb[v])
14940 && redlb[v] < SCIPvarGetUbGlobal(var) )
14941 {
14942 SCIP_Real ub;
14943
14944 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14945 * -> tighten upper bound to x_v <= redlb[v]
14946 */
14947 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14949 redlb[v]);
14950 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14951 assert(!infeasible);
14952
14953 ub = SCIPvarGetUbGlobal(var);
14954 redub[v] = MIN(redub[v], ub);
14955 if( tightened )
14956 (*nchgbds)++;
14957 }
14958 }
14959 if( !SCIPisPositive(scip, obj) )
14960 {
14961 /* making the variable as large as possible does not increase the objective:
14962 * check if all up locks of the variables are due to linear constraints;
14963 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
14964 * constraints redundant is huge, we better do nothing for numerical reasons
14965 */
14967 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
14968 && !SCIPisHugeValue(scip, redub[v])
14969 && redub[v] > SCIPvarGetLbGlobal(var) )
14970 {
14971 SCIP_Real lb;
14972
14973 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14974 * -> tighten lower bound to x_v >= redub[v]
14975 */
14976 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14978 redub[v]);
14979 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14980 assert(!infeasible);
14981
14982 lb = SCIPvarGetLbGlobal(var);
14983 redlb[v] = MAX(redlb[v], lb);
14984 if( tightened )
14985 (*nchgbds)++;
14986 }
14987 }
14988 }
14989
14990 /* upgrade continuous variables to implicit integers */
14991 for( v = nintvars - nbinvars; v < nvars; ++v )
14992 {
14993 SCIP_VAR* var;
14994 SCIP_Bool infeasible;
14995
14996 var = vars[v];
14997 assert(var != NULL);
14998
15000 assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15001 assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15002 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15003
15004 /* we can only conclude implicit integrality if the variable appears in no other constraint */
15005 if( isimplint[v - nintvars + nbinvars]
15006 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15007 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15008 {
15009 /* since we locally copied the variable array we can change the variable type immediately */
15010 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15011 (*nchgvartypes)++;
15012 if( infeasible )
15013 {
15014 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15015 *cutoff = TRUE;
15016
15017 break;
15018 }
15019
15020 SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15022 }
15023 }
15024
15025 /* free temporary memory */
15026 SCIPfreeBufferArray(scip, &conscontvars);
15027 SCIPfreeBufferArray(scip, &isimplint);
15028 SCIPfreeBufferArray(scip, &nlocksup);
15029 SCIPfreeBufferArray(scip, &nlocksdown);
15030 SCIPfreeBufferArray(scip, &redub);
15031 SCIPfreeBufferArray(scip, &redlb);
15032
15033 SCIPfreeBufferArray(scip, &vars);
15034
15035 return SCIP_OKAY;
15036}
15037
15038/** helper function to enforce constraints */
15039static
15041 SCIP* scip, /**< SCIP data structure */
15042 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15043 SCIP_CONS** conss, /**< constraints to process */
15044 int nconss, /**< number of constraints */
15045 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15046 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15047 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15048 )
15049{
15050 SCIP_CONSHDLRDATA* conshdlrdata;
15051 SCIP_Bool checkrelmaxabs;
15052 SCIP_Bool violated;
15053 SCIP_Bool cutoff = FALSE;
15054 int c;
15055
15056 assert(scip != NULL);
15057 assert(conshdlr != NULL);
15058 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15059 assert(result != NULL);
15060
15061 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15062 assert(conshdlrdata != NULL);
15063
15064 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15065
15066 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15067
15068 /* check for violated constraints
15069 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15070 */
15071 *result = SCIP_FEASIBLE;
15072
15073 /* check all useful linear constraints for feasibility */
15074 for( c = 0; c < nusefulconss; ++c )
15075 {
15076 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15077
15078 if( violated )
15079 {
15080 /* insert LP row as cut */
15081 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15082 if ( cutoff )
15083 *result = SCIP_CUTOFF;
15084 else
15085 *result = SCIP_SEPARATED;
15086 }
15087 }
15088
15089 /* check all obsolete linear constraints for feasibility */
15090 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15091 {
15092 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15093
15094 if( violated )
15095 {
15096 /* insert LP row as cut */
15097 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15098 if ( cutoff )
15099 *result = SCIP_CUTOFF;
15100 else
15101 *result = SCIP_SEPARATED;
15102 }
15103 }
15104
15105 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15106
15107 return SCIP_OKAY;
15108}
15109
15110/** adds symmetry information of constraint to a symmetry detection graph */
15111static
15113 SCIP* scip, /**< SCIP pointer */
15114 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15115 SCIP_CONS* cons, /**< constraint */
15116 SYM_GRAPH* graph, /**< symmetry detection graph */
15117 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15118 )
15119{
15120 SCIP_CONSDATA* consdata;
15121 SCIP_VAR** vars;
15122 SCIP_Real* vals;
15123 SCIP_Real constant = 0.0;
15124 SCIP_Real lhs;
15125 SCIP_Real rhs;
15126 int nlocvars;
15127 int nvars;
15128 int i;
15129
15130 assert(scip != NULL);
15131 assert(cons != NULL);
15132 assert(graph != NULL);
15133 assert(success != NULL);
15134
15135 consdata = SCIPconsGetData(cons);
15136 assert(consdata != NULL);
15137
15138 /* get active variables of the constraint */
15139 nvars = SCIPgetNVars(scip);
15140 nlocvars = consdata->nvars;
15141
15142 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
15143 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
15144
15145 for( i = 0; i < nlocvars; ++i )
15146 {
15147 vars[i] = consdata->vars[i];
15148 vals[i] = consdata->vals[i];
15149 }
15150
15151 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15152 lhs = consdata->lhs - constant;
15153 rhs = consdata->rhs - constant;
15154
15155 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15156 * of the same constraint are rated as equal
15157 */
15158 if ( SCIPisInfinity(scip, rhs) )
15159 {
15160 SCIP_Real tmp;
15161 assert(!SCIPisInfinity(scip, -lhs));
15162
15163 for( i = 0; i < nlocvars; ++i )
15164 vals[i] *= -1;
15165 tmp = rhs;
15166 rhs = -lhs;
15167 lhs = -tmp;
15168 }
15169
15170 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
15171 cons, lhs, rhs, success) );
15172
15173 SCIPfreeBufferArray(scip, &vals);
15174 SCIPfreeBufferArray(scip, &vars);
15175
15176 return SCIP_OKAY;
15177}
15178
15179/*
15180 * Callback methods of constraint handler
15181 */
15182
15183/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15184static
15185SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15186{ /*lint --e{715}*/
15187 assert(scip != NULL);
15188 assert(conshdlr != NULL);
15189 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15190
15191 /* call inclusion method of constraint handler */
15193
15194 *valid = TRUE;
15195
15196 return SCIP_OKAY;
15197}
15198
15199/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15200static
15201SCIP_DECL_CONSFREE(consFreeLinear)
15202{ /*lint --e{715}*/
15203 SCIP_CONSHDLRDATA* conshdlrdata;
15204
15205 assert(scip != NULL);
15206 assert(conshdlr != NULL);
15207 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15208
15209 /* free constraint handler data */
15210 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15211 assert(conshdlrdata != NULL);
15212
15213 conshdlrdataFree(scip, &conshdlrdata);
15214
15215 SCIPconshdlrSetData(conshdlr, NULL);
15216
15217 return SCIP_OKAY;
15218}
15219
15220
15221/** initialization method of constraint handler (called after problem was transformed) */
15222static
15223SCIP_DECL_CONSINIT(consInitLinear)
15224{
15225 SCIP_CONSHDLRDATA* conshdlrdata;
15226 int c;
15227
15228 assert(scip != NULL);
15229
15230 /* check for event handler */
15231 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15232 assert(conshdlrdata != NULL);
15233 assert(conshdlrdata->eventhdlr != NULL);
15234 assert(nconss == 0 || conss != NULL);
15235
15236 conshdlrdata->naddconss = 0;
15237
15238 /* catch events for the constraints */
15239 for( c = 0; c < nconss; ++c )
15240 {
15241 /* catch all events */
15242 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15243 }
15244
15245 return SCIP_OKAY;
15246}
15247
15248
15249/** deinitialization method of constraint handler (called before transformed problem is freed) */
15250static
15251SCIP_DECL_CONSEXIT(consExitLinear)
15252{
15253 SCIP_CONSHDLRDATA* conshdlrdata;
15254 int c;
15255
15256 assert(scip != NULL);
15257
15258 /* check for event handler */
15259 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15260 assert(conshdlrdata != NULL);
15261 assert(conshdlrdata->eventhdlr != NULL);
15262
15263 /* drop events for the constraints */
15264 for( c = nconss - 1; c >= 0; --c )
15265 {
15266 SCIP_CONSDATA* consdata;
15267
15268 consdata = SCIPconsGetData(conss[c]);
15269 assert(consdata != NULL);
15270
15271 if( consdata->eventdata != NULL )
15272 {
15273 /* drop all events */
15274 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15275 assert(consdata->eventdata == NULL);
15276 }
15277 }
15278
15279 return SCIP_OKAY;
15280}
15281
15282/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15283static
15285 SCIP* scip, /**< SCIP data structure */
15286 SCIP_Real lhs, /**< left hand side */
15287 SCIP_Real rhs /**< right hand side */
15288 )
15289{
15290 assert(scip != NULL);
15291
15292 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15293}
15294
15295/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15296static
15298 SCIP* scip, /**< SCIP data structure */
15299 SCIP_Real x /**< value */
15300 )
15301{
15302 assert(scip != NULL);
15303
15304 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15305}
15306
15307/** performs linear constraint type classification as used for MIPLIB
15308 *
15309 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15310 *
15311 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15312 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15313 * Similarly, if specialized constraints were created through the API, these are currently not present.
15314 */
15316 SCIP* scip, /**< SCIP data structure */
15317 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15318 )
15319{
15320 int c;
15321 SCIP_CONSHDLR* conshdlr;
15322 SCIP_CONS** conss;
15323 int nconss;
15324
15325 assert(scip != NULL);
15326 assert(linconsstats != NULL);
15327 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15328 assert(conshdlr != NULL);
15329
15331 {
15332 conss = SCIPgetConss(scip);
15333 nconss = SCIPgetNConss(scip);
15334 }
15335 else
15336 {
15337 conss = SCIPconshdlrGetConss(conshdlr);
15338 nconss = SCIPconshdlrGetNConss(conshdlr);
15339 }
15340
15341 /* reset linear constraint type classification */
15342 SCIPlinConsStatsReset(linconsstats);
15343
15344 /* loop through all constraints */
15345 for( c = 0; c < nconss; c++ )
15346 {
15347 SCIP_CONS* cons;
15348 SCIP_CONSDATA* consdata;
15349 SCIP_Real lhs;
15350 SCIP_Real rhs;
15351 int i;
15352
15353 /* get constraint */
15354 cons = conss[c];
15355 assert(cons != NULL);
15356
15357 /* skip constraints that are not handled by the constraint handler */
15358 if( SCIPconsGetHdlr(cons) != conshdlr )
15359 continue;
15360
15361 /* get constraint data */
15362 consdata = SCIPconsGetData(cons);
15363 assert(consdata != NULL);
15364 rhs = consdata->rhs;
15365 lhs = consdata->lhs;
15366
15367 /* merge multiples and delete variables with zero coefficient */
15368 SCIP_CALL( mergeMultiples(scip, cons) );
15369 for( i = 0; i < consdata->nvars; i++ )
15370 {
15371 assert(!SCIPisZero(scip, consdata->vals[i]));
15372 }
15373
15374 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15375 if( consdata->nvars == 0 )
15376 {
15377 SCIPdebugMsg(scip, "classified as EMPTY: ");
15380
15381 continue;
15382 }
15383
15384 /* is constraint of type SCIP_CONSTYPE_FREE? */
15385 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15386 {
15387 SCIPdebugMsg(scip, "classified as FREE: ");
15390
15391 continue;
15392 }
15393
15394 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15395 if( consdata->nvars == 1 )
15396 {
15397 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15400
15401 continue;
15402 }
15403
15404 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15405 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15406 {
15407 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15410
15411 continue;
15412 }
15413
15414 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15415 if( consdata->nvars == 2 )
15416 {
15417 SCIP_LINCONSTYPE constype;
15418
15419 /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15420 if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15421 && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15422 {
15423 constype = SCIP_LINCONSTYPE_PRECEDENCE;
15424 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15425 }
15426 else
15427 {
15428 constype = SCIP_LINCONSTYPE_VARBOUND;
15429 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15430 }
15432
15433 SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15434
15435 continue;
15436 }
15437
15438 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15439 {
15440 SCIP_Real scale;
15441 SCIP_Real b;
15442 SCIP_Bool unmatched;
15443 int nnegbinvars;
15444
15445 unmatched = FALSE;
15446 nnegbinvars = 0;
15447
15448 scale = REALABS(consdata->vals[0]);
15449
15450 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15451 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15452 {
15453 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15454 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15455 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15456 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15457
15458 if( consdata->vals[i] < 0.0 )
15459 nnegbinvars++;
15460 }
15461
15462 if( !unmatched )
15463 {
15464 if( SCIPisEQ(scip, lhs, rhs) )
15465 {
15466 b = rhs/scale + nnegbinvars;
15467 if( SCIPisEQ(scip, 1.0, b) )
15468 {
15469 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15472
15473 continue;
15474 }
15475 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15476 {
15477 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15480
15481 continue;
15482 }
15483 }
15484
15485 /* compute right hand side divided by scale */
15486 if( !SCIPisInfinity(scip, rhs) )
15487 b = rhs/scale + nnegbinvars;
15488 else
15489 b = SCIPinfinity(scip);
15490
15491 if( SCIPisEQ(scip, 1.0, b) )
15492 {
15493 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15496
15497 /* relax right hand side to prevent further classifications */
15498 rhs = SCIPinfinity(scip);
15499 }
15500 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15501 {
15502 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15504
15506
15507 /* relax right hand side to prevent further classifications */
15508 rhs = SCIPinfinity(scip);
15509 }
15510
15511 if( !SCIPisInfinity(scip, lhs) )
15512 b = lhs/scale + nnegbinvars;
15513 else
15514 b = SCIPinfinity(scip);
15515
15516 if( SCIPisEQ(scip, 1.0, b) )
15517 {
15518 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15521
15522 /* relax left hand side to prevent further classifications */
15523 lhs = -SCIPinfinity(scip);
15524 }
15525
15526 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15527 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15528 continue;
15529 }
15530 }
15531
15532 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15533 /* @todo If coefficients or rhs are not integral, we currently do not check
15534 * if the constraint could be scaled (finitely), such that they are.
15535 */
15536 {
15537 SCIP_Real b;
15538 SCIP_Bool unmatched;
15539
15540 b = rhs;
15541 unmatched = FALSE;
15542 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15543 {
15544 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15545 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15546 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15547 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15548
15549 if( SCIPisNegative(scip, consdata->vals[i]) )
15550 b -= consdata->vals[i];
15551 }
15552 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15553
15554 if( !unmatched )
15555 {
15556 if( SCIPisEQ(scip, lhs, rhs) )
15557 {
15558 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15560
15562
15563 continue;
15564 }
15565 else
15566 {
15567 SCIP_Bool matched;
15568
15569 matched = FALSE;
15570 for( i = 0; i < consdata->nvars && !matched; i++ )
15571 {
15572 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15573 }
15574
15575 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15578 }
15579
15580 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15581 if( SCIPisInfinity(scip, -lhs) )
15582 continue;
15583 else
15584 rhs = SCIPinfinity(scip);
15585 }
15586 }
15587
15588 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15589 {
15590 SCIP_Real b;
15591 SCIP_Bool unmatched;
15592
15593 unmatched = FALSE;
15594
15595 b = rhs;
15596 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15597
15598 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15599 {
15600 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15601 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15602 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15603 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15604 }
15605
15606 if( !unmatched )
15607 {
15608 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15611
15612 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15613 if( SCIPisInfinity(scip, -lhs) )
15614 continue;
15615 else
15616 rhs = SCIPinfinity(scip);
15617 }
15618 }
15619
15620 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15621 {
15622 SCIP_Bool unmatched;
15623
15624 unmatched = FALSE;
15625 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15626 {
15627 if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15628 && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15629 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15630 unmatched = TRUE;
15631 }
15632
15633 if( !unmatched )
15634 {
15635 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15638
15639 continue;
15640 }
15641 }
15642
15643 /* no special structure detected */
15644 SCIPdebugMsg(scip, "classified as GENERAL: ");
15646 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15647 }
15648
15649 return SCIP_OKAY;
15650}
15651
15652
15653/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15654static
15655SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15656{ /*lint --e{715}*/
15657 int c;
15658#ifdef SCIP_STATISTIC
15659 SCIP_CONSHDLRDATA* conshdlrdata;
15660 int ngoodconss;
15661 int nallconss;
15662#endif
15663
15664 /* delete all linear constraints that were upgraded to a more specific constraint type;
15665 * make sure, only active variables remain in the remaining constraints
15666 */
15667 assert(scip != NULL);
15668
15669#ifdef SCIP_STATISTIC
15670 /* count number of well behaved linear constraints */
15671 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15672 assert(conshdlrdata != NULL);
15673
15674 ngoodconss = 0;
15675 nallconss = 0;
15676
15677 for( c = 0; c < nconss; ++c )
15678 {
15679 SCIP_CONSDATA* consdata;
15680
15681 if( SCIPconsIsDeleted(conss[c]) )
15682 continue;
15683
15684 consdata = SCIPconsGetData(conss[c]);
15685 assert(consdata != NULL);
15686
15687 if( consdata->upgraded )
15688 continue;
15689
15690 nallconss++;
15691
15693
15694 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15695 ngoodconss++;
15696 }
15697 if( nallconss )
15698 {
15699 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15700 }
15701#endif
15702
15703 for( c = 0; c < nconss; ++c )
15704 {
15705 SCIP_CONSDATA* consdata;
15706
15707 if( SCIPconsIsDeleted(conss[c]) )
15708 continue;
15709
15710 consdata = SCIPconsGetData(conss[c]);
15711 assert(consdata != NULL);
15712
15713 if( consdata->upgraded )
15714 {
15715 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15716 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15717 */
15718 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15719 }
15720 else
15721 {
15722 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15723 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15724 }
15725 }
15726
15727 return SCIP_OKAY;
15728}
15729
15730/** solving process initialization method of constraint handler */
15731static
15732SCIP_DECL_CONSINITSOL(consInitsolLinear)
15733{ /*lint --e{715}*/
15734 /* add nlrow representation to NLP, if NLP had been constructed */
15736 {
15737 int c;
15738 for( c = 0; c < nconss; ++c )
15739 {
15740 SCIP_CALL( addNlrow(scip, conss[c]) );
15741 }
15742 }
15743
15744 return SCIP_OKAY;
15745}
15746
15747/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15748static
15749SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15750{ /*lint --e{715}*/
15751 int c;
15752
15753 assert(scip != NULL);
15754
15755 /* release the rows and nlrows of all constraints */
15756 for( c = 0; c < nconss; ++c )
15757 {
15758 SCIP_CONSDATA* consdata;
15759
15760 consdata = SCIPconsGetData(conss[c]);
15761 assert(consdata != NULL);
15762
15763 if( consdata->row != NULL )
15764 {
15765 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15766 }
15767
15768 if( consdata->nlrow != NULL )
15769 {
15770 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15771 }
15772 }
15773
15774 /* if this is a restart, convert cutpool rows into linear constraints */
15775 if( restart )
15776 {
15777 int ncutsadded;
15778
15779 ncutsadded = 0;
15780
15781 /* create out of all active cuts in cutpool linear constraints */
15782 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15783
15784 if( ncutsadded > 0 )
15785 {
15787 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15788 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15789 * line correctly
15790 */
15792 }
15793 }
15794
15795 return SCIP_OKAY;
15796}
15797
15798
15799/** constraint activation notification method of constraint handler */
15800static
15801SCIP_DECL_CONSACTIVE(consActiveLinear)
15802{ /*lint --e{715}*/
15803 assert(cons != NULL);
15804
15806 {
15807 SCIP_CALL( addNlrow(scip, cons) );
15808 }
15809
15810 return SCIP_OKAY;
15811}
15812
15813/** constraint deactivation notification method of constraint handler */
15814static
15815SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15816{ /*lint --e{715}*/
15817 SCIP_CONSDATA* consdata;
15818
15819 assert(scip != NULL);
15820 assert(conshdlr != NULL);
15821 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15822 assert(cons != NULL );
15823
15824 /* get constraint data */
15825 consdata = SCIPconsGetData(cons);
15826 assert(consdata != NULL);
15827
15828 if( SCIPconsIsDeleted(cons) )
15829 {
15830 SCIP_CONSHDLRDATA* conshdlrdata;
15831
15832 /* check for event handler */
15833 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15834 assert(conshdlrdata != NULL);
15835 assert(conshdlrdata->eventhdlr != NULL);
15836
15837 /* free event data */
15838 if( consdata->eventdata != NULL )
15839 {
15840 /* drop bound change events of variables */
15841 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15842 }
15843 assert(consdata->eventdata == NULL);
15844 }
15845
15846 /* remove row from NLP, if still in solving
15847 * if we are in exitsolve, the whole NLP will be freed anyway
15848 */
15849 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15850 {
15851 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15852 }
15853
15854 return SCIP_OKAY;
15855}
15856
15857
15858/** frees specific constraint data */
15859static
15860SCIP_DECL_CONSDELETE(consDeleteLinear)
15861{ /*lint --e{715}*/
15862 assert(scip != NULL);
15863 assert(conshdlr != NULL);
15864 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15865
15866 if( (*consdata)->eventdata != NULL )
15867 {
15868 SCIP_CONSHDLRDATA* conshdlrdata;
15869
15870 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15871 assert(conshdlrdata != NULL);
15872
15873 /* drop all events */
15874 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15875 assert((*consdata)->eventdata == NULL);
15876 }
15877
15878 /* free linear constraint */
15879 SCIP_CALL( consdataFree(scip, consdata) );
15880
15881 return SCIP_OKAY;
15882}
15883
15884
15885/** transforms constraint data into data belonging to the transformed problem */
15886static
15887SCIP_DECL_CONSTRANS(consTransLinear)
15888{ /*lint --e{715}*/
15889 SCIP_CONSDATA* sourcedata;
15890 SCIP_CONSDATA* targetdata;
15891
15892 /*debugMsg(scip, "Trans method of linear constraints\n");*/
15893
15894 assert(scip != NULL);
15895 assert(conshdlr != NULL);
15896 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15898 assert(sourcecons != NULL);
15899 assert(targetcons != NULL);
15900
15901 sourcedata = SCIPconsGetData(sourcecons);
15902 assert(sourcedata != NULL);
15903 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15904
15905 /* create linear constraint data for target constraint */
15906 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15907
15908#ifndef NDEBUG
15909 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15910 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15911 {
15912 int n;
15913 for(n = targetdata->nvars - 1; n >= 0; --n )
15914 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15915 }
15916#endif
15917
15918 /* create target constraint */
15919 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15920 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15921 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15922 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15923 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15924
15925 return SCIP_OKAY;
15926}
15927
15928
15929/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15930static
15931SCIP_DECL_CONSINITLP(consInitlpLinear)
15932{ /*lint --e{715}*/
15933 int c;
15934
15935 assert(scip != NULL);
15936 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15937
15938 *infeasible = FALSE;
15939
15940 for( c = 0; c < nconss && !(*infeasible); ++c )
15941 {
15942 assert(SCIPconsIsInitial(conss[c]));
15943 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15944 }
15945
15946 return SCIP_OKAY;
15947}
15948
15949
15950/** separation method of constraint handler for LP solutions */
15951static
15952SCIP_DECL_CONSSEPALP(consSepalpLinear)
15953{ /*lint --e{715}*/
15954 SCIP_CONSHDLRDATA* conshdlrdata;
15955 SCIP_Real loclowerbound;
15956 SCIP_Real glblowerbound;
15957 SCIP_Real cutoffbound;
15958 SCIP_Real maxbound;
15959 SCIP_Bool separatecards;
15960 SCIP_Bool cutoff;
15961 int c;
15962 int depth;
15963 int nrounds;
15964 int maxsepacuts;
15965 int ncuts;
15966
15967 assert(scip != NULL);
15968 assert(conshdlr != NULL);
15969 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15970 assert(result != NULL);
15971
15972 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15973 assert(conshdlrdata != NULL);
15974 depth = SCIPgetDepth(scip);
15975 nrounds = SCIPgetNSepaRounds(scip);
15976
15977 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15978
15979 *result = SCIP_DIDNOTRUN;
15980
15981 /* only call the separator a given number of times at each node */
15982 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15983 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15984 return SCIP_OKAY;
15985
15986 /* get the maximal number of cuts allowed in a separation round */
15987 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15988
15989 /* check if we want to produce knapsack cardinality cuts at this node */
15990 loclowerbound = SCIPgetLocalLowerbound(scip);
15991 glblowerbound = SCIPgetLowerbound(scip);
15992 cutoffbound = SCIPgetCutoffbound(scip);
15993 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
15994 separatecards = SCIPisLE(scip, loclowerbound, maxbound);
15995 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
15996
15997 *result = SCIP_DIDNOTFIND;
15998 ncuts = 0;
15999 cutoff = FALSE;
16000
16001 /* check all useful linear constraints for feasibility */
16002 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16003 {
16004 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16005 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16006 }
16007
16008 /* adjust return value */
16009 if( cutoff )
16010 *result = SCIP_CUTOFF;
16011 else if( ncuts > 0 )
16012 *result = SCIP_SEPARATED;
16013
16014 /* combine linear constraints to get more cuts */
16015 /**@todo further cuts of linear constraints */
16016
16017 return SCIP_OKAY;
16018}
16019
16020
16021/** separation method of constraint handler for arbitrary primal solutions */
16022static
16023SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16024{ /*lint --e{715}*/
16025 SCIP_CONSHDLRDATA* conshdlrdata;
16026 int c;
16027 int depth;
16028 int nrounds;
16029 int maxsepacuts;
16030 int ncuts;
16031 SCIP_Bool cutoff;
16032
16033 assert(scip != NULL);
16034 assert(conshdlr != NULL);
16035 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16036 assert(result != NULL);
16037
16038 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16039 assert(conshdlrdata != NULL);
16040 depth = SCIPgetDepth(scip);
16041 nrounds = SCIPgetNSepaRounds(scip);
16042
16043 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16044
16045 *result = SCIP_DIDNOTRUN;
16046
16047 /* only call the separator a given number of times at each node */
16048 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16049 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16050 return SCIP_OKAY;
16051
16052 /* get the maximal number of cuts allowed in a separation round */
16053 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16054
16055 *result = SCIP_DIDNOTFIND;
16056 ncuts = 0;
16057 cutoff = FALSE;
16058
16059 /* check all useful linear constraints for feasibility */
16060 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16061 {
16062 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16063 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16064 }
16065
16066 /* adjust return value */
16067 if( cutoff )
16068 *result = SCIP_CUTOFF;
16069 else if( ncuts > 0 )
16070 *result = SCIP_SEPARATED;
16071
16072 /* combine linear constraints to get more cuts */
16073 /**@todo further cuts of linear constraints */
16074
16075 return SCIP_OKAY;
16076}
16077
16078
16079/** constraint enforcing method of constraint handler for LP solutions */
16080static
16081SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16082{ /*lint --e{715}*/
16083 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16084
16085 return SCIP_OKAY;
16086}
16087
16088/** constraint enforcing method of constraint handler for relaxation solutions */
16089static
16090SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16091{ /*lint --e{715}*/
16092 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16093
16094 return SCIP_OKAY;
16095}
16096
16097/** constraint enforcing method of constraint handler for pseudo solutions */
16098static
16099SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16100{ /*lint --e{715}*/
16101 SCIP_CONSHDLRDATA* conshdlrdata;
16102 SCIP_Bool checkrelmaxabs;
16103 SCIP_Bool violated;
16104 int c;
16105
16106 assert(scip != NULL);
16107 assert(conshdlr != NULL);
16108 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16109 assert(result != NULL);
16110
16111 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16112 assert(conshdlrdata != NULL);
16113
16114 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16115
16116 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16117
16118 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16119 if( objinfeasible )
16120 {
16121 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16122
16123 *result = SCIP_DIDNOTRUN;
16124 return SCIP_OKAY;
16125 }
16126
16127 /* check all linear constraints for feasibility */
16128 violated = FALSE;
16129 for( c = 0; c < nconss && !violated; ++c )
16130 {
16131 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16132 }
16133
16134 if( violated )
16135 *result = SCIP_INFEASIBLE;
16136 else
16137 *result = SCIP_FEASIBLE;
16138
16139 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16140
16141 return SCIP_OKAY;
16142}
16143
16144
16145/** feasibility check method of constraint handler for integral solutions */
16146static
16147SCIP_DECL_CONSCHECK(consCheckLinear)
16148{ /*lint --e{715}*/
16149 SCIP_CONSHDLRDATA* conshdlrdata;
16150 SCIP_Bool checkrelmaxabs;
16151 int c;
16152
16153 assert(scip != NULL);
16154 assert(conshdlr != NULL);
16155 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16156 assert(result != NULL);
16157
16158 *result = SCIP_FEASIBLE;
16159
16160 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16161 assert(conshdlrdata != NULL);
16162
16163 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16164
16165 /*debugMsg(scip, "Check method of linear constraints\n");*/
16166
16167 /* check all linear constraints for feasibility */
16168 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16169 {
16170 SCIP_Bool violated = FALSE;
16171 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16172
16173 if( violated )
16174 {
16175 *result = SCIP_INFEASIBLE;
16176
16177 if( printreason )
16178 {
16179 SCIP_CONSDATA* consdata;
16180 SCIP_Real activity;
16181
16182 consdata = SCIPconsGetData(conss[c]);
16183 assert( consdata != NULL);
16184
16185 activity = consdataGetActivity(scip, consdata, sol);
16186
16187 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16188 SCIPinfoMessage(scip, NULL, ";\n");
16189
16190 if( activity == SCIP_INVALID ) /*lint !e777*/
16191 SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16192 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16193 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16194 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16195 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16196 }
16197 }
16198 }
16199
16200 return SCIP_OKAY;
16201}
16202
16203
16204/** domain propagation method of constraint handler */
16205static
16206SCIP_DECL_CONSPROP(consPropLinear)
16207{ /*lint --e{715}*/
16208 SCIP_CONSHDLRDATA* conshdlrdata;
16209 SCIP_Bool rangedrowpropagation = FALSE;
16210 SCIP_Bool tightenbounds;
16211 SCIP_Bool cutoff;
16212
16213 int nchgbds;
16214 int i;
16215
16216 assert(scip != NULL);
16217 assert(conshdlr != NULL);
16218 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16219 assert(result != NULL);
16220
16221 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16222 assert(conshdlrdata != NULL);
16223
16224 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16225
16226 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16227 if( SCIPinProbing(scip) )
16228 tightenbounds = TRUE;
16229 else
16230 {
16231 int depth;
16232 int propfreq;
16233 int tightenboundsfreq;
16234 int rangedrowfreq;
16235
16236 depth = SCIPgetDepth(scip);
16237 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16238 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16239 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16240 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16241
16242 /* check if we want to do ranged row propagation */
16243 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16244 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16245 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16246 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16247 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16248 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16249 }
16250
16251 cutoff = FALSE;
16252 nchgbds = 0;
16253
16254 /* process constraints marked for propagation */
16255 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16256 {
16258 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16259 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16260 }
16261
16262 /* adjust result code */
16263 if( cutoff )
16264 *result = SCIP_CUTOFF;
16265 else if( nchgbds > 0 )
16266 *result = SCIP_REDUCEDDOM;
16267 else
16268 *result = SCIP_DIDNOTFIND;
16269
16270 return SCIP_OKAY;
16271}
16272
16273
16274#define MAXCONSPRESOLROUNDS 10
16275/** presolving method of constraint handler */
16276static
16277SCIP_DECL_CONSPRESOL(consPresolLinear)
16278{ /*lint --e{715}*/
16279 SCIP_CONSHDLRDATA* conshdlrdata;
16280 SCIP_CONS* cons;
16281 SCIP_CONSDATA* consdata;
16282 SCIP_Real minactivity;
16283 SCIP_Real maxactivity;
16284 SCIP_Bool isminacttight;
16285 SCIP_Bool ismaxacttight;
16286 SCIP_Bool isminsettoinfinity;
16287 SCIP_Bool ismaxsettoinfinity;
16288 SCIP_Bool cutoff;
16289 int oldnfixedvars;
16290 int oldnaggrvars;
16291 int oldnchgbds;
16292 int oldndelconss;
16293 int oldnupgdconss;
16294 int oldnchgcoefs;
16295 int oldnchgsides;
16296 int firstchange;
16297 int firstupgradetry;
16298 int c;
16299
16300 assert(scip != NULL);
16301 assert(conshdlr != NULL);
16302 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16303 assert(result != NULL);
16304
16305 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16306
16307 /* remember old preprocessing counters */
16308 cutoff = FALSE;
16309 oldnfixedvars = *nfixedvars;
16310 oldnaggrvars = *naggrvars;
16311 oldnchgbds = *nchgbds;
16312 oldndelconss = *ndelconss;
16313 oldnupgdconss = *nupgdconss;
16314 oldnchgcoefs = *nchgcoefs;
16315 oldnchgsides = *nchgsides;
16316
16317 /* get constraint handler data */
16318 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16319 assert(conshdlrdata != NULL);
16320
16321 /* process single constraints */
16322 firstchange = INT_MAX;
16323 firstupgradetry = INT_MAX;
16324 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16325 {
16326 int npresolrounds;
16327 SCIP_Bool infeasible;
16328
16329 infeasible = FALSE;
16330
16331 cons = conss[c];
16332 assert(SCIPconsIsActive(cons));
16333 consdata = SCIPconsGetData(cons);
16334 assert(consdata != NULL);
16335
16336 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16337 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16338 {
16339 consdata->lhs = consdata->rhs;
16340 assert(consdata->row == NULL);
16341 }
16342
16343 if( consdata->eventdata == NULL )
16344 {
16345 /* catch bound change events of variables */
16346 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16347 assert(consdata->eventdata != NULL);
16348 }
16349
16350 /* constraint should not be already presolved in the initial round */
16351 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16352 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16353 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16354 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16355
16356 /* incorporate fixings and aggregations in constraint */
16357 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16358
16359 if( infeasible )
16360 {
16361 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16362 cutoff = TRUE;
16363 break;
16364 }
16365
16366 assert(consdata->removedfixings);
16367
16368 /* we can only presolve linear constraints, that are not modifiable */
16369 if( SCIPconsIsModifiable(cons) )
16370 continue;
16371
16372 /* remember the first changed constraint to begin the next aggregation round with */
16373 if( firstchange == INT_MAX && consdata->changed )
16374 firstchange = c;
16375
16376 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16377 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16378 firstupgradetry = c;
16379
16380 /* check, if constraint is already preprocessed */
16381 if( consdata->presolved )
16382 continue;
16383
16384 assert(SCIPconsIsActive(cons));
16385
16386 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16388
16389 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16390 * to avoid nearly infinite cycling due to very small bound changes)
16391 */
16392 npresolrounds = 0;
16393 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16394 {
16395 assert(!cutoff);
16396 npresolrounds++;
16397
16398 /* mark constraint being presolved and propagated */
16399 consdata->presolved = TRUE;
16401
16402 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16403
16404 if( infeasible )
16405 {
16406 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16407 cutoff = TRUE;
16408 break;
16409 }
16410
16411 /* tighten left and right hand side due to integrality */
16412 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16413
16414 if( infeasible )
16415 {
16416 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16417 cutoff = TRUE;
16418 break;
16419 }
16420
16421 /* check bounds */
16422 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16423 {
16424 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16425 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16426 cutoff = TRUE;
16427 break;
16428 }
16429
16430 /* tighten variable's bounds */
16431 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16432 if( cutoff )
16433 break;
16434
16435 /* check for fixed variables */
16436 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16437 if( cutoff )
16438 break;
16439
16440 /* if the maximal coefficient is large, recompute the activities before infeasibility and redundancy checks */
16441 if( ( consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP )
16442 || ( consdata->validminabsval && consdata->minabsval < MINVALRECOMP ) )
16443 {
16446 }
16447
16448 /* get activity bounds */
16449 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
16450 &isminsettoinfinity, &ismaxsettoinfinity);
16451
16452 /* check constraint for infeasibility and redundancy */
16453 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16454 {
16455 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16456 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16457 cutoff = TRUE;
16458 break;
16459 }
16460 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16461 {
16462 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16463 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16464 SCIP_CALL( SCIPdelCons(scip, cons) );
16465 assert(!SCIPconsIsActive(cons));
16466
16467 if( !consdata->upgraded )
16468 (*ndelconss)++;
16469 break;
16470 }
16471 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16472 {
16473 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16474 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16475 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16476 if( !consdata->upgraded )
16477 (*nchgsides)++;
16478 }
16479 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16480 {
16481 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16482 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16484 if( !consdata->upgraded )
16485 (*nchgsides)++;
16486 }
16487
16488 /* handle empty constraint */
16489 if( consdata->nvars == 0 )
16490 {
16491 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16492 {
16493 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16494 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16495 cutoff = TRUE;
16496 }
16497 else
16498 {
16499 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16500 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16501 SCIP_CALL( SCIPdelCons(scip, cons) );
16502 assert(!SCIPconsIsActive(cons));
16503
16504 if( !consdata->upgraded )
16505 (*ndelconss)++;
16506 }
16507 break;
16508 }
16509
16510 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16511 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16512
16513 /* try to simplify inequalities */
16514 if( conshdlrdata->simplifyinequalities )
16515 {
16516 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16517
16518 if( cutoff )
16519 break;
16520 }
16521
16522 /* aggregation variable in equations */
16523 if( conshdlrdata->aggregatevariables )
16524 {
16525 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16526 if( cutoff )
16527 break;
16528 }
16529 }
16530
16531 if( !cutoff && !SCIPisStopped(scip) )
16532 {
16533 /* perform ranged row propagation */
16534 if( conshdlrdata->rangedrowpropagation )
16535 {
16536 int lastnfixedvars;
16537
16538 lastnfixedvars = *nfixedvars;
16539
16540 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16541 if( !cutoff )
16542 {
16543 if( lastnfixedvars < *nfixedvars )
16544 {
16545 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16546 }
16547 }
16548 }
16549
16550 /* extract cliques from constraint */
16551 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16552 {
16553 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16554 nfixedvars, nchgbds, &cutoff) );
16555
16556 /* check if the constraint got redundant or infeasible */
16557 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16558 {
16559 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16560 {
16561 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16562 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16563 cutoff = TRUE;
16564 }
16565 else
16566 {
16567 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16568 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16569 SCIP_CALL( SCIPdelCons(scip, cons) );
16570 assert(!SCIPconsIsActive(cons));
16571
16572 if( !consdata->upgraded )
16573 (*ndelconss)++;
16574 }
16575 }
16576 }
16577
16578 /* convert special equalities */
16579 if( !cutoff && SCIPconsIsActive(cons) )
16580 {
16581 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16582 }
16583
16584 /* apply dual presolving for variables that appear in only one constraint */
16585 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16586 {
16587 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16588 }
16589
16590 /* check if an inequality is parallel to the objective function */
16591 if( !cutoff && SCIPconsIsActive(cons) )
16592 {
16593 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16594 }
16595
16596 /* remember the first changed constraint to begin the next aggregation round with */
16597 if( firstchange == INT_MAX && consdata->changed )
16598 firstchange = c;
16599
16600 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16601 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16602 firstupgradetry = c;
16603 }
16604
16605 /* singleton column stuffing */
16606 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16607 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16608 {
16609 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16610 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16611
16612 /* handle empty constraint */
16613 if( consdata->nvars == 0 )
16614 {
16615 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16616 {
16617 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16618 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16619 cutoff = TRUE;
16620 }
16621 else
16622 {
16623 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16624 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16625 SCIP_CALL( SCIPdelCons(scip, cons) );
16626 assert(!SCIPconsIsActive(cons));
16627
16628 if( !consdata->upgraded )
16629 (*ndelconss)++;
16630 }
16631 break;
16632 }
16633 }
16634 }
16635
16636 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16637 * only apply this expensive procedure in exhaustive presolving timing
16638 */
16639 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16640 {
16641 assert(firstchange >= 0);
16642
16643 if( firstchange < nconss && conshdlrdata->presolusehashing )
16644 {
16645 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16646 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16647 ndelconss, nchgsides) );
16648 }
16649
16650 if( firstchange < nconss && conshdlrdata->presolpairwise )
16651 {
16652 SCIP_CONS** usefulconss;
16653 int nusefulconss;
16654 int firstchangenew;
16655 SCIP_Longint npaircomparisons;
16656
16657 npaircomparisons = 0;
16658 oldndelconss = *ndelconss;
16659 oldnchgsides = *nchgsides;
16660 oldnchgcoefs = *nchgcoefs;
16661
16662 /* allocate temporary memory */
16663 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16664
16665 nusefulconss = 0;
16666 firstchangenew = -1;
16667 for( c = 0; c < nconss; ++c )
16668 {
16669 /* update firstchange */
16670 if( c == firstchange )
16671 firstchangenew = nusefulconss;
16672
16673 /* ignore inactive and modifiable constraints */
16674 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16675 continue;
16676
16677 usefulconss[nusefulconss] = conss[c];
16678 ++nusefulconss;
16679 }
16680 firstchange = firstchangenew;
16681 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16682
16683 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16684 {
16685 /* constraint has become inactive or modifiable during pairwise presolving */
16686 if( usefulconss[c] == NULL )
16687 continue;
16688
16689 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16690
16691 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16692 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16693 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16694
16695 if( npaircomparisons > conshdlrdata->nmincomparisons )
16696 {
16697 assert(npaircomparisons > 0);
16698 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16699 break;
16700 oldndelconss = *ndelconss;
16701 oldnchgsides = *nchgsides;
16702 oldnchgcoefs = *nchgcoefs;
16703 npaircomparisons = 0;
16704 }
16705 }
16706 /* free temporary memory */
16707 SCIPfreeBufferArray(scip, &usefulconss);
16708 }
16709 }
16710
16711 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16712 * in linear constraints and we therefore have full information about it
16713 */
16714 if( !cutoff && firstupgradetry < nconss
16715 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16716 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16717 )
16718 {
16719 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16720 {
16721 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds, nchgvartypes) );
16722 }
16723 }
16724
16725 /* try to upgrade constraints into a more specific constraint type;
16726 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16727 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16728 */
16729 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16730 {
16731 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16732 {
16733 cons = conss[c];
16734
16735 /* don't upgrade modifiable constraints */
16736 if( SCIPconsIsModifiable(cons) )
16737 continue;
16738
16739 consdata = SCIPconsGetData(cons);
16740 assert(consdata != NULL);
16741
16742 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16743 if( consdata->upgradetried )
16744 continue;
16745 /* @todo force that upgrade will be performed later? */
16746 if( !consdata->presolved )
16747 continue;
16748
16749 consdata->upgradetried = TRUE;
16750 if( SCIPconsIsActive(cons) )
16751 {
16752 SCIP_CONS* upgdcons;
16753
16754 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16755 if( upgdcons != NULL )
16756 {
16757 /* add the upgraded constraint to the problem */
16758 SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16759 SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16760 (*nupgdconss)++;
16761
16762 /* mark the linear constraint being upgraded and to be removed after presolving;
16763 * don't delete it directly, because it may help to preprocess other linear constraints
16764 */
16765 assert(!consdata->upgraded);
16766 consdata->upgraded = TRUE;
16767
16768 /* delete upgraded inequalities immediately;
16769 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16770 */
16771 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16772 || !conshdlrdata->presolpairwise
16773 || (conshdlrdata->maxaggrnormscale == 0.0) )
16774 {
16775 SCIP_CALL( SCIPdelCons(scip, cons) );
16776 }
16777 }
16778 }
16779 }
16780 }
16781
16782 /* return the correct result code */
16783 if( cutoff )
16784 *result = SCIP_CUTOFF;
16785 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16786 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16787 *result = SCIP_SUCCESS;
16788 else
16789 *result = SCIP_DIDNOTFIND;
16790
16791 return SCIP_OKAY;
16792}
16793
16794
16795/** propagation conflict resolving method of constraint handler */
16796static
16797SCIP_DECL_CONSRESPROP(consRespropLinear)
16798{ /*lint --e{715}*/
16799 assert(scip != NULL);
16800 assert(cons != NULL);
16801 assert(result != NULL);
16802
16803 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16804
16805 return SCIP_OKAY;
16806}
16807
16808
16809/** variable rounding lock method of constraint handler */
16810static
16811SCIP_DECL_CONSLOCK(consLockLinear)
16812{ /*lint --e{715}*/
16813 SCIP_CONSDATA* consdata;
16814 SCIP_Bool haslhs;
16815 SCIP_Bool hasrhs;
16816 int i;
16817
16818 assert(scip != NULL);
16819 assert(cons != NULL);
16820 consdata = SCIPconsGetData(cons);
16821 assert(consdata != NULL);
16822
16823 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16824 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16825
16826 /* update rounding locks of every single variable */
16827 for( i = 0; i < consdata->nvars; ++i )
16828 {
16829 if( SCIPisPositive(scip, consdata->vals[i]) )
16830 {
16831 if( haslhs )
16832 {
16833 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16834 }
16835 if( hasrhs )
16836 {
16837 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16838 }
16839 }
16840 else
16841 {
16842 if( haslhs )
16843 {
16844 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16845 }
16846 if( hasrhs )
16847 {
16848 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16849 }
16850 }
16851 }
16852
16853 return SCIP_OKAY;
16854}
16855
16856
16857/** variable deletion method of constraint handler */
16858static
16859SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16860{
16861 assert(scip != NULL);
16862 assert(conshdlr != NULL);
16863 assert(conss != NULL || nconss == 0);
16864
16865 if( nconss > 0 )
16866 {
16867 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16868 }
16869
16870 return SCIP_OKAY;
16871}
16872
16873/** constraint display method of constraint handler */
16874static
16875SCIP_DECL_CONSPRINT(consPrintLinear)
16876{ /*lint --e{715}*/
16877 assert(scip != NULL);
16878 assert(conshdlr != NULL);
16879 assert(cons != NULL);
16880
16882
16883 return SCIP_OKAY;
16884}
16885
16886/** constraint copying method of constraint handler */
16887static
16888SCIP_DECL_CONSCOPY(consCopyLinear)
16889{ /*lint --e{715}*/
16890 SCIP_VAR** sourcevars;
16891 SCIP_Real* sourcecoefs;
16892 const char* consname;
16893 int nvars;
16894
16895 assert(scip != NULL);
16896 assert(sourcescip != NULL);
16897 assert(sourcecons != NULL);
16898
16899 /* get variables and coefficients of the source constraint */
16900 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16901 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16902 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16903
16904 if( name != NULL )
16905 consname = name;
16906 else
16907 consname = SCIPconsGetName(sourcecons);
16908
16909 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16910 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16911 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16912 assert(cons != NULL || *valid == FALSE);
16913
16914 /* @todo should also the checkabsolute flag of the constraint be copied? */
16915
16916 return SCIP_OKAY;
16917}
16918
16919/** find operators '<=', '==', '>=', [free] in input string and return those places
16920 *
16921 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16922 */
16923static
16925 const char* str, /**< null terminated input string */
16926 char** firstoperator, /**< pointer to store the string starting at the first operator */
16927 char** secondoperator, /**< pointer to store the string starting at the second operator */
16928 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16929 )
16930{
16931 char* curr;
16932
16933 assert(str != NULL);
16934 assert(firstoperator != NULL);
16935 assert(secondoperator != NULL);
16936
16937 *firstoperator = NULL;
16938 *secondoperator = NULL;
16939
16940 curr = (char*)str;
16941 *success = TRUE;
16942
16943 /* loop over the input string to find all operators */
16944 while( *curr && *success )
16945 {
16946 SCIP_Bool found = FALSE;
16947 int increment = 1;
16948
16949 /* try if we found a possible operator */
16950 switch( *curr )
16951 {
16952 case '<':
16953 case '=':
16954 case '>':
16955
16956 /* check if the two characters curr[0,1] form an operator together */
16957 if( curr[1] == '=' )
16958 {
16959 found = TRUE;
16960
16961 /* update increment to continue after this operator */
16962 increment = 2;
16963 }
16964 break;
16965 case '[':
16966 if( strncmp(curr, "[free]", 6) == 0 )
16967 {
16968 found = TRUE;
16969
16970 /* update increment to continue after this operator */
16971 increment = 6;
16972 }
16973 break;
16974 default:
16975 break;
16976 }
16977
16978 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16979 if( found )
16980 {
16981 if( *firstoperator == NULL )
16982 {
16983 *firstoperator = curr;
16984 }
16985 else
16986 {
16987 if( *secondoperator != NULL )
16988 {
16989 SCIPerrorMessage("Found more than two operators in line %s\n", str);
16990 *success = FALSE;
16991 }
16992 else if( strncmp(*firstoperator, "<=", 2) != 0 )
16993 {
16994 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16995 *success = FALSE;
16996 }
16997 else if( strncmp(curr, "<=", 2) != 0 )
16998 {
16999 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17000 *success = FALSE;
17001 }
17002
17003 *secondoperator = curr;
17004 }
17005 }
17006
17007 curr += increment;
17008 }
17009
17010 /* check if we did find at least one operator */
17011 if( *success )
17012 {
17013 if( *firstoperator == NULL )
17014 {
17015 SCIPerrorMessage("Could not find any operator in line %s\n", str);
17016 *success = FALSE;
17017 }
17018 }
17019}
17020
17021/** constraint parsing method of constraint handler */
17022static
17023SCIP_DECL_CONSPARSE(consParseLinear)
17024{ /*lint --e{715}*/
17025 SCIP_VAR** vars;
17026 SCIP_Real* coefs;
17027 int nvars;
17028 int coefssize;
17029 int requsize;
17030 SCIP_Real lhs;
17031 SCIP_Real rhs;
17032 char* endptr;
17033 char* firstop;
17034 char* secondop;
17035 SCIP_Bool operatorsuccess;
17036 char* lhsstrptr;
17037 char* rhsstrptr;
17038 char* varstrptr;
17039
17040 assert(scip != NULL);
17041 assert(success != NULL);
17042 assert(str != NULL);
17043 assert(name != NULL);
17044 assert(cons != NULL);
17045
17046 /* set left and right hand side to their default values */
17047 lhs = -SCIPinfinity(scip);
17048 rhs = SCIPinfinity(scip);
17049
17050 (*success) = FALSE;
17051
17052 /* return of string empty */
17053 if( !*str )
17054 return SCIP_OKAY;
17055
17056 /* ignore whitespace */
17057 SCIP_CALL( SCIPskipSpace((char**)&str) );
17058
17059 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17060 * and the special word [free]
17061 */
17062 findOperators(str, &firstop, &secondop, &operatorsuccess);
17063
17064 /* if the grammar is not valid for parsing a linear constraint, return */
17065 if( ! operatorsuccess )
17066 return SCIP_OKAY;
17067
17068 varstrptr = (char *)str;
17069 lhsstrptr = rhsstrptr = NULL;
17070 assert(firstop != NULL);
17071
17072 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17073 switch( *firstop )
17074 {
17075 case '<':
17076 assert(firstop[1] == '=');
17077 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17078 if( secondop != NULL )
17079 {
17080 assert(secondop[0] == '<' && secondop[1] == '=');
17081 lhsstrptr = (char *)str;
17082 varstrptr = firstop + 2;
17083 rhsstrptr = secondop + 2;
17084 }
17085 else
17086 {
17087 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17088 lhsstrptr = NULL;
17089 varstrptr = (char *)str;
17090 rhsstrptr = firstop + 2;
17091 }
17092 break;
17093 case '>':
17094 assert(firstop[1] == '=');
17095 assert(secondop == NULL);
17096 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17097 lhsstrptr = firstop + 2;
17098 break;
17099 case '=':
17100 assert(firstop[1] == '=');
17101 assert(secondop == NULL);
17102 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17103 rhsstrptr = firstop + 2;
17104 lhsstrptr = firstop + 2;
17105 break;
17106 case '[':
17107 assert(strncmp(firstop, "[free]", 6) == 0);
17108 assert(secondop == NULL);
17109 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17110 break;
17111 default:
17112 /* it should not be possible that a different character appears in that position */
17113 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17114 return SCIP_READERROR;
17115 }
17116
17117 /* parse left hand side, if necessary */
17118 if( lhsstrptr != NULL )
17119 {
17120 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17121 {
17122 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17123 return SCIP_OKAY;
17124 }
17125
17126 /* in case of an equation, assign the left also to the right hand side */
17127 if( rhsstrptr == lhsstrptr )
17128 rhs = lhs;
17129 }
17130
17131 /* parse right hand side, if different from left hand side */
17132 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17133 {
17134 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17135 {
17136 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17137 return SCIP_OKAY;
17138 }
17139 }
17140
17141 /* initialize buffers for storing the variables and coefficients */
17142 coefssize = 100;
17143 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17144 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17145
17146 assert(varstrptr != NULL);
17147
17148 /* parse linear sum to get variables and coefficients */
17149 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17150
17151 if( *success && requsize > coefssize )
17152 {
17153 /* realloc buffers and try again */
17154 coefssize = requsize;
17155 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17156 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17157
17158 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17159 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17160 }
17161
17162 if( !*success )
17163 {
17164 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17165 }
17166 else
17167 {
17168 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17169 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17170 }
17171
17172 SCIPfreeBufferArray(scip, &coefs);
17173 SCIPfreeBufferArray(scip, &vars);
17174
17175 return SCIP_OKAY;
17176}
17177
17178
17179/** constraint method of constraint handler which returns the variables (if possible) */
17180static
17181SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17182{ /*lint --e{715}*/
17183 SCIP_CONSDATA* consdata;
17184
17185 consdata = SCIPconsGetData(cons);
17186 assert(consdata != NULL);
17187
17188 if( varssize < consdata->nvars )
17189 (*success) = FALSE;
17190 else
17191 {
17192 assert(vars != NULL);
17193
17194 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17195 (*success) = TRUE;
17196 }
17197
17198 return SCIP_OKAY;
17199}
17200
17201/**! [Callback for the number of variables]*/
17202/** constraint method of constraint handler which returns the number of variables (if possible) */
17203static
17204SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17205{ /*lint --e{715}*/
17206 SCIP_CONSDATA* consdata;
17207
17208 consdata = SCIPconsGetData(cons);
17209 assert(consdata != NULL);
17210
17211 (*nvars) = consdata->nvars;
17212 (*success) = TRUE;
17213
17214 return SCIP_OKAY;
17215}
17216/**! [Callback for the number of variables]*/
17217
17218/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17219static
17220SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17221{ /*lint --e{715}*/
17222 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17223
17224 return SCIP_OKAY;
17225}
17226
17227/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17228static
17229SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17230{ /*lint --e{715}*/
17231 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17232
17233 return SCIP_OKAY;
17234}
17235
17236/*
17237 * Callback methods of event handler
17238 */
17239
17240/** execution method of event handler */
17241static
17242SCIP_DECL_EVENTEXEC(eventExecLinear)
17243{ /*lint --e{715}*/
17244 SCIP_CONS* cons;
17245 SCIP_CONSDATA* consdata;
17246 SCIP_VAR* var;
17247 SCIP_EVENTTYPE eventtype;
17248
17249 assert(scip != NULL);
17250 assert(eventhdlr != NULL);
17251 assert(eventdata != NULL);
17252 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17253 assert(event != NULL);
17254
17255 cons = eventdata->cons;
17256 assert(cons != NULL);
17257 consdata = SCIPconsGetData(cons);
17258 assert(consdata != NULL);
17259
17260 /* we can skip events droped for deleted constraints */
17261 if( SCIPconsIsDeleted(cons) )
17262 return SCIP_OKAY;
17263
17264 eventtype = SCIPeventGetType(event);
17265 var = SCIPeventGetVar(event);
17266
17267 if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17268 {
17269 SCIP_Real oldbound;
17270 SCIP_Real newbound;
17271 SCIP_Real val;
17272 int varpos;
17273
17274 varpos = eventdata->varpos;
17275 assert(0 <= varpos && varpos < consdata->nvars);
17276 oldbound = SCIPeventGetOldbound(event);
17277 newbound = SCIPeventGetNewbound(event);
17278 assert(var != NULL);
17279 assert(consdata->vars[varpos] == var);
17280 val = consdata->vals[varpos];
17281
17282 /* we only need to update the activities if the constraint is active,
17283 * otherwise we mark them to be invalid
17284 */
17285 if( SCIPconsIsActive(cons) )
17286 {
17287 /* update the activity values */
17288 if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17289 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17290 else
17291 {
17292 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17293 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17294 }
17295 }
17296 else
17298
17299 consdata->presolved = FALSE;
17300 consdata->rangedrowpropagated = 0;
17301
17302 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17303 if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17304 {
17306
17307 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17308 if( consdata->maxactdeltavar == var )
17309 {
17310 consdata->maxactdelta = SCIP_INVALID;
17311 consdata->maxactdeltavar = NULL;
17312 }
17313
17314 /* check whether bound tightening might now be successful */
17315 if( consdata->boundstightened > 0)
17316 {
17317 switch( eventtype )
17318 {
17320 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17321 consdata->boundstightened = 0;
17322 break;
17324 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17325 consdata->boundstightened = 0;
17326 break;
17327 default:
17328 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17329 return SCIP_INVALIDDATA;
17330 }
17331 }
17332 }
17333 /* update maximal activity delta if a bound was relaxed */
17334 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17335 {
17336 SCIP_Real lb;
17337 SCIP_Real ub;
17338 SCIP_Real domain;
17339 SCIP_Real delta;
17340
17341 assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17342
17343 lb = SCIPvarGetLbLocal(var);
17344 ub = SCIPvarGetUbLocal(var);
17345
17346 domain = ub - lb;
17347 delta = REALABS(val) * domain;
17348
17349 if( delta > consdata->maxactdelta )
17350 {
17351 consdata->maxactdelta = delta;
17352 consdata->maxactdeltavar = var;
17353 }
17354 }
17355 }
17356 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17357 {
17358 /* we want to remove the fixed variable */
17359 consdata->presolved = FALSE;
17360 consdata->removedfixings = FALSE;
17361 consdata->rangedrowpropagated = 0;
17362
17363 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17364 if( consdata->maxactdeltavar == var )
17365 {
17366 consdata->maxactdelta = SCIP_INVALID;
17367 consdata->maxactdeltavar = NULL;
17368 }
17369 }
17370 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17371 {
17372 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17375 consdata->presolved = FALSE;
17376 }
17377 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17378 {
17379 SCIP_Real oldbound;
17380 SCIP_Real newbound;
17381 SCIP_Real val;
17382 int varpos;
17383
17384 varpos = eventdata->varpos;
17385 assert(0 <= varpos && varpos < consdata->nvars);
17386 oldbound = SCIPeventGetOldbound(event);
17387 newbound = SCIPeventGetNewbound(event);
17388 assert(var != NULL);
17389 assert(consdata->vars[varpos] == var);
17390 val = consdata->vals[varpos];
17391
17392 consdata->rangedrowpropagated = 0;
17393
17394 /* update the activity values */
17395 if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17396 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17397 else
17398 {
17399 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17400 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17401 }
17402
17403 /* if the variable is binary but not fixed it had to become binary due to this global change */
17405 {
17407 consdata->indexsorted = FALSE;
17408 else
17409 consdata->coefsorted = FALSE;
17410 }
17411 }
17412 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17413 {
17415
17416 /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17417 consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17418
17419 /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17420 consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17421 }
17422 else
17423 {
17424 assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17425 consdata->varsdeleted = TRUE;
17426 }
17427
17428 return SCIP_OKAY;
17429}
17430
17431
17432/*
17433 * Callback methods of conflict handler
17434 */
17435
17436/** conflict processing method of conflict handler (called when conflict was found) */
17437static
17438SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17439{ /*lint --e{715}*/
17440 SCIP_VAR** vars;
17441 SCIP_Real* vals;
17442 SCIP_Real lhs;
17443 int i;
17444
17445 assert(scip != NULL);
17446 assert(conflicthdlr != NULL);
17447 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17448 assert(bdchginfos != NULL || nbdchginfos == 0);
17449 assert(result != NULL);
17450
17451 /* don't process already resolved conflicts */
17452 if( resolved )
17453 {
17454 *result = SCIP_DIDNOTRUN;
17455 return SCIP_OKAY;
17456 }
17457
17458 *result = SCIP_DIDNOTFIND;
17459
17460 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17461 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17462 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17463 lhs = 1.0;
17464 for( i = 0; i < nbdchginfos; ++i )
17465 {
17466 assert(bdchginfos != NULL);
17467
17468 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17469
17470 /* we can only treat binary variables */
17471 /**@todo extend linear conflict constraints to some non-binary cases */
17472 if( !SCIPvarIsBinary(vars[i]) )
17473 break;
17474
17475 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17476 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17477 vals[i] = 1.0;
17478 else
17479 {
17480 vals[i] = -1.0;
17481 lhs -= 1.0;
17482 }
17483 }
17484
17485 if( i == nbdchginfos )
17486 {
17487 SCIP_CONS* cons;
17488 SCIP_CONS* upgdcons;
17489 char consname[SCIP_MAXSTRLEN];
17490
17491 /* create a constraint out of the conflict set */
17493 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17494 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17495
17496 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17497 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17498 if( upgdcons != NULL )
17499 {
17500 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17501 cons = upgdcons;
17502 }
17503
17504 /* add conflict to SCIP */
17505 SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17506
17507 *result = SCIP_CONSADDED;
17508 }
17509
17510 /* free temporary memory */
17511 SCIPfreeBufferArray(scip, &vals);
17512 SCIPfreeBufferArray(scip, &vars);
17513
17514 return SCIP_OKAY;
17515}
17516
17517
17518/*
17519 * Nonlinear constraint upgrading
17520 */
17521
17522/** tries to upgrade a nonlinear constraint into a linear constraint */
17523static
17524SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17525{
17526 SCIP_CONSDATA* consdata;
17527 SCIP_EXPR* expr;
17528 SCIP_Real lhs;
17529 SCIP_Real rhs;
17530 int i;
17531
17532 assert(nupgdconss != NULL);
17533 assert(upgdconss != NULL);
17534 assert(upgdconsssize > 0);
17535
17536 expr = SCIPgetExprNonlinear(cons);
17537 assert(expr != NULL);
17538
17539 /* not a linear constraint if the expression is not a sum
17540 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17541 */
17542 if( !SCIPisExprSum(scip, expr) )
17543 return SCIP_OKAY;
17544
17545 /* if at least one child is not a variable, then not a linear constraint */
17546 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17547 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17548 return SCIP_OKAY;
17549
17550 /* consider constant part of the sum expression */
17553
17554 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17555 0, NULL, NULL, lhs, rhs,
17559 SCIPconsIsStickingAtNode(cons)) );
17560 assert(upgdconss[0] != NULL);
17561
17562 consdata = SCIPconsGetData(upgdconss[0]);
17563
17564 /* add linear terms */
17566 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17567 {
17569 }
17570
17571 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17572 consdata->checkabsolute = TRUE;
17573
17574 *nupgdconss = 1;
17575
17576 SCIPdebugMsg(scip, "created linear constraint:\n");
17577 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17578
17579 return SCIP_OKAY;
17580} /*lint !e715*/
17581
17582/*
17583 * constraint specific interface methods
17584 */
17585
17586/** creates the handler for linear constraints and includes it in SCIP */
17588 SCIP* scip /**< SCIP data structure */
17589 )
17590{
17591 SCIP_CONSHDLRDATA* conshdlrdata;
17592 SCIP_CONSHDLR* conshdlr;
17593 SCIP_EVENTHDLR* eventhdlr;
17594 SCIP_CONFLICTHDLR* conflicthdlr;
17595
17596 assert(scip != NULL);
17597
17598 /* create event handler for bound change events */
17600 eventExecLinear, NULL) );
17601
17602 /* create conflict handler for linear constraints */
17604 conflictExecLinear, NULL) );
17605
17606 /* create constraint handler data */
17607 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17608
17609 /* include constraint handler */
17612 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17613 conshdlrdata) );
17614
17615 assert(conshdlr != NULL);
17616
17617 /* set non-fundamental callbacks via specific setter functions */
17618 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17619 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17620 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17621 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17622 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17623 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17624 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17625 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17626 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17627 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17628 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17629 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17630 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17631 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17632 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17634 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17637 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17638 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17640 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17641 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17642 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17643 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17644
17645 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17646 {
17647 /* include the linear constraint upgrade in the nonlinear constraint handler */
17649 }
17650
17651 /* add linear constraint handler parameters */
17653 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17654 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17655 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17657 "constraints/" CONSHDLR_NAME "/maxrounds",
17658 "maximal number of separation rounds per node (-1: unlimited)",
17659 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17661 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17662 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17663 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17665 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17666 "maximal number of cuts separated per separation round",
17667 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17669 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17670 "maximal number of cuts separated per separation round in the root node",
17671 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17673 "constraints/" CONSHDLR_NAME "/presolpairwise",
17674 "should pairwise constraint comparison be performed in presolving?",
17675 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17677 "constraints/" CONSHDLR_NAME "/presolusehashing",
17678 "should hash table be used for detecting redundant constraints in advance",
17679 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17681 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17682 "number for minimal pairwise presolve comparisons",
17683 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17685 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17686 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17687 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17689 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17690 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17691 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17693 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17694 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17695 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17697 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17698 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17699 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17701 "constraints/" CONSHDLR_NAME "/separateall",
17702 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17703 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17705 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17706 "should presolving search for aggregations in equations",
17707 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17709 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17710 "should presolving try to simplify inequalities",
17711 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17713 "constraints/" CONSHDLR_NAME "/dualpresolving",
17714 "should dual presolving steps be performed?",
17715 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17717 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17718 "should stuffing of singleton continuous variables be performed?",
17719 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17721 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17722 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17723 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17725 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17726 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17728 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17729 "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)?",
17730 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17732 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17733 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17734 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17736 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17737 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17738 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17740 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17741 "should presolving try to detect subsets of constraints parallel to the objective function?",
17742 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17744 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17745 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17746 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17748 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17749 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17750 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17752 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17753 "maximum depth to apply ranged row propagation",
17754 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17756 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17757 "frequency for applying ranged row propagation",
17758 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17760 "constraints/" CONSHDLR_NAME "/multaggrremove",
17761 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17762 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17764 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17765 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17766 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17768 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17769 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17770 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17772 "constraints/" CONSHDLR_NAME "/extractcliques",
17773 "should Cliques be extracted?",
17774 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17775
17776 return SCIP_OKAY;
17777}
17778
17779/** includes a linear constraint update method into the linear constraint handler */
17781 SCIP* scip, /**< SCIP data structure */
17782 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17783 int priority, /**< priority of upgrading method */
17784 const char* conshdlrname /**< name of the constraint handler */
17785 )
17786{
17787 SCIP_CONSHDLR* conshdlr;
17788 SCIP_CONSHDLRDATA* conshdlrdata;
17789 SCIP_LINCONSUPGRADE* linconsupgrade;
17791 char paramdesc[SCIP_MAXSTRLEN];
17792
17793 assert(scip != NULL);
17794 assert(linconsupgd != NULL);
17795 assert(conshdlrname != NULL );
17796
17797 /* find the linear constraint handler */
17798 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17799 if( conshdlr == NULL )
17800 {
17801 SCIPerrorMessage("linear constraint handler not found\n");
17802 return SCIP_PLUGINNOTFOUND;
17803 }
17804
17805 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17806 assert(conshdlrdata != NULL);
17807
17808 /* check if linear constraint update method already exists in constraint handler data */
17809 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17810 {
17811 /* create a linear constraint upgrade data object */
17812 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17813
17814 /* insert linear constraint update method into constraint handler data */
17815 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17816
17817 /* adds parameter to turn on and off the upgrading step */
17818 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17819 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17821 paramname, paramdesc,
17822 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17823 }
17824
17825 return SCIP_OKAY;
17826}
17827
17828/** creates and captures a linear constraint
17829 *
17830 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17831 */
17833 SCIP* scip, /**< SCIP data structure */
17834 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17835 const char* name, /**< name of constraint */
17836 int nvars, /**< number of nonzeros in the constraint */
17837 SCIP_VAR** vars, /**< array with variables of constraint entries */
17838 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17839 SCIP_Real lhs, /**< left hand side of constraint */
17840 SCIP_Real rhs, /**< right hand side of constraint */
17841 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17842 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17843 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17844 * Usually set to TRUE. */
17845 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17846 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17847 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17848 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17849 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17850 * Usually set to TRUE. */
17851 SCIP_Bool local, /**< is constraint only valid locally?
17852 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17853 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17854 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17855 * adds coefficients to this constraint. */
17856 SCIP_Bool dynamic, /**< is constraint subject to aging?
17857 * Usually set to FALSE. Set to TRUE for own cuts which
17858 * are separated as constraints. */
17859 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17860 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17861 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17862 * if it may be moved to a more global node?
17863 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17864 )
17865{
17866 SCIP_CONSHDLR* conshdlr;
17867 SCIP_CONSDATA* consdata;
17868 int j;
17869
17870 assert(scip != NULL);
17871 assert(cons != NULL);
17872
17873 /* find the linear constraint handler */
17874 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17875 if( conshdlr == NULL )
17876 {
17877 SCIPerrorMessage("linear constraint handler not found\n");
17878 return SCIP_PLUGINNOTFOUND;
17879 }
17880
17881 for( j = 0; j < nvars; ++j )
17882 {
17883 if( SCIPisInfinity(scip, REALABS(vals[j])) )
17884 {
17885 SCIPerrorMessage("coefficient of variable <%s> is infinite.\n", SCIPvarGetName(vars[j]));
17886 SCIPABORT();
17887 return SCIP_INVALIDDATA;
17888 }
17889 }
17890
17891 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17892 * constraint after presolving we have to ensure that it holds active variables
17893 */
17894 if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17895 {
17896 SCIP_VAR** consvars;
17897 SCIP_Real* consvals;
17898 SCIP_Real constant = 0.0;
17899 int nconsvars;
17900 int requiredsize;
17901
17902 nconsvars = nvars;
17903 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17904 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17905
17906 /* get active variables for new constraint */
17907 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17908
17909 /* if space was not enough we need to resize the buffers */
17910 if( requiredsize > nconsvars )
17911 {
17912 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17913 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17914
17915 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17916 assert(requiredsize <= nconsvars);
17917 }
17918
17919 /* adjust sides and check that we do not subtract infinity values */
17920 if( SCIPisInfinity(scip, REALABS(constant)) )
17921 {
17922 if( constant < 0.0 )
17923 {
17924 if( SCIPisInfinity(scip, lhs) )
17925 {
17926 SCIPfreeBufferArray(scip, &consvals);
17927 SCIPfreeBufferArray(scip, &consvars);
17928
17929 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);
17930
17931 SCIPABORT();
17932 return SCIP_INVALIDDATA; /*lint !e527*/
17933 }
17934 if( SCIPisInfinity(scip, rhs) )
17935 {
17936 SCIPfreeBufferArray(scip, &consvals);
17937 SCIPfreeBufferArray(scip, &consvars);
17938
17939 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);
17940
17941 SCIPABORT();
17942 return SCIP_INVALIDDATA; /*lint !e527*/
17943 }
17944
17945 lhs = -SCIPinfinity(scip);
17946 rhs = -SCIPinfinity(scip);
17947 }
17948 else
17949 {
17950 if( SCIPisInfinity(scip, -lhs) )
17951 {
17952 SCIPfreeBufferArray(scip, &consvals);
17953 SCIPfreeBufferArray(scip, &consvars);
17954
17955 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);
17956
17957 SCIPABORT();
17958 return SCIP_INVALIDDATA; /*lint !e527*/
17959 }
17960 if( SCIPisInfinity(scip, -rhs) )
17961 {
17962 SCIPfreeBufferArray(scip, &consvals);
17963 SCIPfreeBufferArray(scip, &consvars);
17964
17965 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);
17966
17967 SCIPABORT();
17968 return SCIP_INVALIDDATA; /*lint !e527*/
17969 }
17970
17971 lhs = SCIPinfinity(scip);
17972 rhs = SCIPinfinity(scip);
17973 }
17974 }
17975 else
17976 {
17977 if( !SCIPisInfinity(scip, REALABS(lhs)) )
17978 lhs -= constant;
17979 if( !SCIPisInfinity(scip, REALABS(rhs)) )
17980 rhs -= constant;
17981
17982 if( SCIPisInfinity(scip, -lhs) )
17983 lhs = -SCIPinfinity(scip);
17984 else if( SCIPisInfinity(scip, lhs) )
17985 lhs = SCIPinfinity(scip);
17986
17987 if( SCIPisInfinity(scip, rhs) )
17988 rhs = SCIPinfinity(scip);
17989 else if( SCIPisInfinity(scip, -rhs) )
17990 rhs = -SCIPinfinity(scip);
17991 }
17992
17993 /* create constraint data */
17994 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17995 assert(consdata != NULL);
17996
17997 SCIPfreeBufferArray(scip, &consvals);
17998 SCIPfreeBufferArray(scip, &consvars);
17999 }
18000 else
18001 {
18002 /* create constraint data */
18003 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18004 assert(consdata != NULL);
18005 }
18006
18007#ifndef NDEBUG
18008 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18009 if( check || enforce )
18010 {
18011 int n;
18012 for(n = consdata->nvars - 1; n >= 0; --n )
18013 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18014 }
18015#endif
18016
18017 /* create constraint */
18018 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18019 local, modifiable, dynamic, removable, stickingatnode) );
18020
18021 return SCIP_OKAY;
18022}
18023
18024/** creates and captures a linear constraint
18025 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18026 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18027 *
18028 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18029 *
18030 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18031 */
18033 SCIP* scip, /**< SCIP data structure */
18034 SCIP_CONS** cons, /**< pointer to hold the created constraint */
18035 const char* name, /**< name of constraint */
18036 int nvars, /**< number of nonzeros in the constraint */
18037 SCIP_VAR** vars, /**< array with variables of constraint entries */
18038 SCIP_Real* vals, /**< array with coefficients of constraint entries */
18039 SCIP_Real lhs, /**< left hand side of constraint */
18040 SCIP_Real rhs /**< right hand side of constraint */
18041 )
18042{
18043 assert(scip != NULL);
18044
18045 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18047
18048 return SCIP_OKAY;
18049}
18050
18051/** creates by copying and captures a linear constraint */
18053 SCIP* scip, /**< target SCIP data structure */
18054 SCIP_CONS** cons, /**< pointer to store the created target constraint */
18055 SCIP* sourcescip, /**< source SCIP data structure */
18056 const char* name, /**< name of constraint */
18057 int nvars, /**< number of variables in source variable array */
18058 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18059 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18060 SCIP_Real lhs, /**< left hand side of the linear constraint */
18061 SCIP_Real rhs, /**< right hand side of the linear constraint */
18062 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18063 * variables of the target SCIP */
18064 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18065 * target constraints */
18066 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18067 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18068 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18069 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18070 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18071 SCIP_Bool local, /**< is constraint only valid locally? */
18072 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18073 SCIP_Bool dynamic, /**< is constraint subject to aging? */
18074 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18075 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18076 * if it may be moved to a more global node? */
18077 SCIP_Bool global, /**< create a global or a local copy? */
18078 SCIP_Bool* valid /**< pointer to store if the copying was valid */
18079 )
18080{
18081 SCIP_VAR** vars;
18082 SCIP_Real* coefs;
18083
18084 SCIP_Real constant;
18085 int requiredsize;
18086 int v;
18087 SCIP_Bool success;
18088
18089 if( SCIPisGT(scip, lhs, rhs) )
18090 {
18091 *valid = FALSE;
18092 return SCIP_OKAY;
18093 }
18094
18095 (*valid) = TRUE;
18096
18097 if( nvars == 0 )
18098 {
18099 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18100 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18101 return SCIP_OKAY;
18102 }
18103
18104 /* duplicate variable array */
18105 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
18106
18107 /* duplicate coefficient array */
18108 if( sourcecoefs != NULL )
18109 {
18110 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18111 }
18112 else
18113 {
18114 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18115 for( v = 0; v < nvars; ++v )
18116 coefs[v] = 1.0;
18117 }
18118
18119 constant = 0.0;
18120
18121 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18122 * the target SCIP
18123 */
18124 if( !SCIPvarIsOriginal(vars[0]) )
18125 {
18126 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18127
18128 if( requiredsize > nvars )
18129 {
18130 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18131 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18132
18133 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18134 assert(requiredsize <= nvars);
18135 }
18136 }
18137 else
18138 {
18139 for( v = 0; v < nvars; ++v )
18140 {
18141 assert(SCIPvarIsOriginal(vars[v]));
18142 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18143 assert(vars[v] != NULL);
18144 }
18145 }
18146
18147 success = TRUE;
18148 /* map variables of the source constraint to variables of the target SCIP */
18149 for( v = 0; v < nvars && success; ++v )
18150 {
18151 SCIP_VAR* var;
18152 var = vars[v];
18153
18154 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18155 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18156
18157 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18158 assert(!(success) || vars[v] != NULL);
18159 }
18160
18161 /* only create the target constraint, if all variables could be copied */
18162 if( success )
18163 {
18164 if( !SCIPisInfinity(scip, -lhs) )
18165 lhs -= constant;
18166
18167 if( !SCIPisInfinity(scip, rhs) )
18168 rhs -= constant;
18169
18170 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18171 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18172 }
18173 else
18174 *valid = FALSE;
18175
18176 /* free buffer array */
18177 SCIPfreeBufferArray(scip, &coefs);
18178 SCIPfreeBufferArray(scip, &vars);
18179
18180 return SCIP_OKAY;
18181}
18182
18183/** adds coefficient to linear constraint (if it is not zero) */
18185 SCIP* scip, /**< SCIP data structure */
18186 SCIP_CONS* cons, /**< constraint data */
18187 SCIP_VAR* var, /**< variable of constraint entry */
18188 SCIP_Real val /**< coefficient of constraint entry */
18189 )
18190{
18191 assert(scip != NULL);
18192 assert(cons != NULL);
18193 assert(var != NULL);
18194
18195 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18196 {
18197 SCIPerrorMessage("constraint is not linear\n");
18198 return SCIP_INVALIDDATA;
18199 }
18200
18201 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18202 * constraint after presolving we have to ensure that it holds active variables
18203 */
18205 {
18206 SCIP_CONSDATA* consdata;
18207 SCIP_VAR** consvars;
18208 SCIP_Real* consvals;
18209 SCIP_Real constant = 0.0;
18210 SCIP_Real rhs;
18211 SCIP_Real lhs;
18212 int nconsvars;
18213 int requiredsize;
18214 int v;
18215
18216 nconsvars = 1;
18217 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18218 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18219 consvars[0] = var;
18220 consvals[0] = val;
18221
18222 /* get active variables for new constraint */
18223 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18224
18225 /* if space was not enough we need to resize the buffers */
18226 if( requiredsize > nconsvars )
18227 {
18228 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18229 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18230
18231 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18232 assert(requiredsize <= nconsvars);
18233 }
18234
18235 consdata = SCIPconsGetData(cons);
18236 assert(consdata != NULL);
18237
18238 lhs = consdata->lhs;
18239 rhs = consdata->rhs;
18240
18241 /* adjust sides and check that we do not subtract infinity values */
18242 /* constant is infinite */
18243 if( SCIPisInfinity(scip, REALABS(constant)) )
18244 {
18245 if( constant < 0.0 )
18246 {
18247 if( SCIPisInfinity(scip, lhs) )
18248 {
18249 SCIPfreeBufferArray(scip, &consvals);
18250 SCIPfreeBufferArray(scip, &consvars);
18251
18252 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));
18253
18254 SCIPABORT();
18255 return SCIP_INVALIDDATA; /*lint !e527*/
18256 }
18257 if( SCIPisInfinity(scip, rhs) )
18258 {
18259 SCIPfreeBufferArray(scip, &consvals);
18260 SCIPfreeBufferArray(scip, &consvars);
18261
18262 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));
18263
18264 SCIPABORT();
18265 return SCIP_INVALIDDATA; /*lint !e527*/
18266 }
18267
18268 lhs = -SCIPinfinity(scip);
18269 rhs = -SCIPinfinity(scip);
18270 }
18271 else
18272 {
18273 if( SCIPisInfinity(scip, -lhs) )
18274 {
18275 SCIPfreeBufferArray(scip, &consvals);
18276 SCIPfreeBufferArray(scip, &consvars);
18277
18278 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));
18279
18280 SCIPABORT();
18281 return SCIP_INVALIDDATA; /*lint !e527*/
18282 }
18283 if( SCIPisInfinity(scip, -rhs) )
18284 {
18285 SCIPfreeBufferArray(scip, &consvals);
18286 SCIPfreeBufferArray(scip, &consvars);
18287
18288 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));
18289
18290 SCIPABORT();
18291 return SCIP_INVALIDDATA; /*lint !e527*/
18292 }
18293
18294 lhs = SCIPinfinity(scip);
18295 rhs = SCIPinfinity(scip);
18296 }
18297 }
18298 /* constant is not infinite */
18299 else
18300 {
18301 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18302 lhs -= constant;
18303 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18304 rhs -= constant;
18305
18306 if( SCIPisInfinity(scip, -lhs) )
18307 lhs = -SCIPinfinity(scip);
18308 else if( SCIPisInfinity(scip, lhs) )
18309 lhs = SCIPinfinity(scip);
18310
18311 if( SCIPisInfinity(scip, rhs) )
18312 rhs = SCIPinfinity(scip);
18313 else if( SCIPisInfinity(scip, -rhs) )
18314 rhs = -SCIPinfinity(scip);
18315 }
18316
18317 /* add all active variables to constraint */
18318 for( v = nconsvars - 1; v >= 0; --v )
18319 {
18320 if( !SCIPisZero(scip, consvals[v]) )
18321 {
18322 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18323 }
18324 }
18325
18326 /* update left and right hand sides */
18327 SCIP_CALL( chgLhs(scip, cons, lhs));
18328 SCIP_CALL( chgRhs(scip, cons, rhs));
18329
18330 SCIPfreeBufferArray(scip, &consvals);
18331 SCIPfreeBufferArray(scip, &consvars);
18332 }
18333 else if( !SCIPisZero(scip, val) )
18334 {
18335 SCIP_CALL( addCoef(scip, cons, var, val) );
18336 }
18337
18338 return SCIP_OKAY;
18339}
18340
18341/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18342 * not yet contained in the constraint
18343 *
18344 * @note This method may only be called during problem creation stage for an original constraint and variable.
18345 *
18346 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18347 */
18349 SCIP* scip, /**< SCIP data structure */
18350 SCIP_CONS* cons, /**< constraint data */
18351 SCIP_VAR* var, /**< variable of constraint entry */
18352 SCIP_Real val /**< new coefficient of constraint entry */
18353 )
18354{
18355 SCIP_CONSDATA* consdata;
18356 SCIP_VAR** vars;
18357 SCIP_Bool found;
18358 int i;
18359
18360 assert(scip != NULL);
18361 assert(cons != NULL);
18362 assert(var != NULL);
18363
18364 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18365 {
18366 SCIPerrorMessage("constraint is not linear\n");
18367 return SCIP_INVALIDDATA;
18368 }
18369
18371 {
18372 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18373 return SCIP_INVALIDDATA;
18374 }
18375
18376 consdata = SCIPconsGetData(cons);
18377 assert(consdata != NULL);
18378
18379 vars = consdata->vars;
18380 found = FALSE;
18381 i = 0;
18382 while( i < consdata->nvars )
18383 {
18384 if( vars[i] == var )
18385 {
18386 if( found || SCIPisZero(scip, val) )
18387 {
18388 SCIP_CALL( delCoefPos(scip, cons, i) );
18389
18390 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18391 i--;
18392 }
18393 else
18394 {
18395 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18396 }
18397 found = TRUE;
18398 }
18399 i++;
18400 }
18401
18402 if( !found )
18403 {
18404 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18405 }
18406
18407 return SCIP_OKAY;
18408}
18409
18410/** deletes variable from linear constraint
18411 *
18412 * @note This method may only be called during problem creation stage for an original constraint and variable.
18413 *
18414 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18415 */
18417 SCIP* scip, /**< SCIP data structure */
18418 SCIP_CONS* cons, /**< constraint data */
18419 SCIP_VAR* var /**< variable of constraint entry */
18420 )
18421{
18422 assert(scip != NULL);
18423 assert(cons != NULL);
18424 assert(var != NULL);
18425
18426 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18427
18428 return SCIP_OKAY;
18429}
18430
18431/** gets left hand side of linear constraint */
18433 SCIP* scip, /**< SCIP data structure */
18434 SCIP_CONS* cons /**< constraint data */
18435 )
18436{
18437 SCIP_CONSDATA* consdata;
18438
18439 assert(scip != NULL);
18440 assert(cons != NULL);
18441
18442 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18443 {
18444 SCIPerrorMessage("constraint is not linear\n");
18445 SCIPABORT();
18446 return SCIP_INVALID; /*lint !e527*/
18447 }
18448
18449 consdata = SCIPconsGetData(cons);
18450 assert(consdata != NULL);
18451
18452 return consdata->lhs;
18453}
18454
18455/** gets right hand side of linear constraint */
18457 SCIP* scip, /**< SCIP data structure */
18458 SCIP_CONS* cons /**< constraint data */
18459 )
18460{
18461 SCIP_CONSDATA* consdata;
18462
18463 assert(scip != NULL);
18464 assert(cons != NULL);
18465
18466 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18467 {
18468 SCIPerrorMessage("constraint is not linear\n");
18469 SCIPABORT();
18470 return SCIP_INVALID; /*lint !e527*/
18471 }
18472
18473 consdata = SCIPconsGetData(cons);
18474 assert(consdata != NULL);
18475
18476 return consdata->rhs;
18477}
18478
18479/** changes left hand side of linear constraint */
18481 SCIP* scip, /**< SCIP data structure */
18482 SCIP_CONS* cons, /**< constraint data */
18483 SCIP_Real lhs /**< new left hand side */
18484 )
18485{
18486 assert(scip != NULL);
18487 assert(cons != NULL);
18488
18489 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18490 {
18491 SCIPerrorMessage("constraint is not linear\n");
18492 return SCIP_INVALIDDATA;
18493 }
18494
18495 SCIP_CALL( chgLhs(scip, cons, lhs) );
18496
18497 return SCIP_OKAY;
18498}
18499
18500/** changes right hand side of linear constraint */
18502 SCIP* scip, /**< SCIP data structure */
18503 SCIP_CONS* cons, /**< constraint data */
18504 SCIP_Real rhs /**< new right hand side */
18505 )
18506{
18507 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18508 {
18509 SCIPerrorMessage("constraint is not linear\n");
18510 return SCIP_INVALIDDATA;
18511 }
18512
18513 SCIP_CALL( chgRhs(scip, cons, rhs) );
18514
18515 return SCIP_OKAY;
18516}
18517
18518/** gets the number of variables in the linear constraint */
18520 SCIP* scip, /**< SCIP data structure */
18521 SCIP_CONS* cons /**< constraint data */
18522 )
18523{
18524 SCIP_CONSDATA* consdata;
18525
18526 assert(scip != NULL);
18527 assert(cons != NULL);
18528
18529 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18530 {
18531 SCIPerrorMessage("constraint is not linear\n");
18532 SCIPABORT();
18533 return -1; /*lint !e527*/
18534 }
18535
18536 consdata = SCIPconsGetData(cons);
18537 assert(consdata != NULL);
18538
18539 return consdata->nvars;
18540}
18541
18542/** gets the array of variables in the linear constraint; the user must not modify this array! */
18544 SCIP* scip, /**< SCIP data structure */
18545 SCIP_CONS* cons /**< constraint data */
18546 )
18547{
18548 SCIP_CONSDATA* consdata;
18549
18550 assert(scip != NULL);
18551 assert(cons != NULL);
18552
18553 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18554 {
18555 SCIPerrorMessage("constraint is not linear\n");
18556 SCIPABORT();
18557 return NULL; /*lint !e527*/
18558 }
18559
18560 consdata = SCIPconsGetData(cons);
18561 assert(consdata != NULL);
18562
18563 return consdata->vars;
18564}
18565
18566/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18568 SCIP* scip, /**< SCIP data structure */
18569 SCIP_CONS* cons /**< constraint data */
18570 )
18571{
18572 SCIP_CONSDATA* consdata;
18573
18574 assert(scip != NULL);
18575 assert(cons != NULL);
18576
18577 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18578 {
18579 SCIPerrorMessage("constraint is not linear\n");
18580 SCIPABORT();
18581 return NULL; /*lint !e527*/
18582 }
18583
18584 consdata = SCIPconsGetData(cons);
18585 assert(consdata != NULL);
18586
18587 return consdata->vals;
18588}
18589
18590/** gets the activity of the linear constraint in the given solution
18591 *
18592 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18593 * comprises positive and negative infinity contributions
18594 */
18596 SCIP* scip, /**< SCIP data structure */
18597 SCIP_CONS* cons, /**< constraint data */
18598 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18599 )
18600{
18601 SCIP_CONSDATA* consdata;
18602
18603 assert(scip != NULL);
18604 assert(cons != NULL);
18605
18606 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18607 {
18608 SCIPerrorMessage("constraint is not linear\n");
18609 SCIPABORT();
18610 return SCIP_INVALID; /*lint !e527*/
18611 }
18612
18613 consdata = SCIPconsGetData(cons);
18614 assert(consdata != NULL);
18615
18616 if( consdata->row != NULL )
18617 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18618 else
18619 return consdataGetActivity(scip, consdata, sol);
18620}
18621
18622/** gets the feasibility of the linear constraint in the given solution */
18624 SCIP* scip, /**< SCIP data structure */
18625 SCIP_CONS* cons, /**< constraint data */
18626 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18627 )
18628{
18629 SCIP_CONSDATA* consdata;
18630
18631 assert(scip != NULL);
18632 assert(cons != NULL);
18633
18634 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18635 {
18636 SCIPerrorMessage("constraint is not linear\n");
18637 SCIPABORT();
18638 return SCIP_INVALID; /*lint !e527*/
18639 }
18640
18641 consdata = SCIPconsGetData(cons);
18642 assert(consdata != NULL);
18643
18644 if( consdata->row != NULL )
18645 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18646 else
18647 return consdataGetFeasibility(scip, consdata, sol);
18648}
18649
18650/** gets the dual solution of the linear constraint in the current LP */
18652 SCIP* scip, /**< SCIP data structure */
18653 SCIP_CONS* cons /**< constraint data */
18654 )
18655{
18656 SCIP_CONSDATA* consdata;
18657
18658 assert(scip != NULL);
18659 assert(cons != NULL);
18660 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18661
18662 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18663 {
18664 SCIPerrorMessage("constraint is not linear\n");
18665 SCIPABORT();
18666 return SCIP_INVALID; /*lint !e527*/
18667 }
18668
18669 consdata = SCIPconsGetData(cons);
18670 assert(consdata != NULL);
18671
18672 if( consdata->row != NULL )
18673 return SCIProwGetDualsol(consdata->row);
18674 else
18675 return 0.0;
18676}
18677
18678/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18680 SCIP* scip, /**< SCIP data structure */
18681 SCIP_CONS* cons /**< constraint data */
18682 )
18683{
18684 SCIP_CONSDATA* consdata;
18685
18686 assert(scip != NULL);
18687 assert(cons != NULL);
18688 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18689
18690 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18691 {
18692 SCIPerrorMessage("constraint is not linear\n");
18693 SCIPABORT();
18694 return SCIP_INVALID; /*lint !e527*/
18695 }
18696
18697 consdata = SCIPconsGetData(cons);
18698 assert(consdata != NULL);
18699
18700 if( consdata->row != NULL )
18701 return SCIProwGetDualfarkas(consdata->row);
18702 else
18703 return 0.0;
18704}
18705
18706/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18707 * the user must not modify the row!
18708 */
18710 SCIP* scip, /**< SCIP data structure */
18711 SCIP_CONS* cons /**< constraint data */
18712 )
18713{
18714 SCIP_CONSDATA* consdata;
18715
18716 assert(scip != NULL);
18717 assert(cons != NULL);
18718
18719 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18720 {
18721 SCIPerrorMessage("constraint is not linear\n");
18722 SCIPABORT();
18723 return NULL; /*lint !e527*/
18724 }
18725
18726 consdata = SCIPconsGetData(cons);
18727 assert(consdata != NULL);
18728
18729 return consdata->row;
18730}
18731
18732/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18734 SCIP* scip, /**< SCIP data structure */
18735 SCIP_CONS* cons, /**< source constraint to try to convert */
18736 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18737 )
18738{
18739 SCIP_CONSHDLR* conshdlr;
18740 SCIP_CONSHDLRDATA* conshdlrdata;
18741 SCIP_CONSDATA* consdata;
18742 SCIP_VAR* var;
18743 SCIP_Real val;
18744 SCIP_Real lb;
18745 SCIP_Real ub;
18746 SCIP_Real poscoeffsum;
18747 SCIP_Real negcoeffsum;
18748 SCIP_Bool infeasible;
18749 SCIP_Bool integral;
18750 int nchgsides = 0;
18751 int nposbin;
18752 int nnegbin;
18753 int nposint;
18754 int nnegint;
18755 int nposimpl;
18756 int nnegimpl;
18757 int nposimplbin;
18758 int nnegimplbin;
18759 int nposcont;
18760 int nnegcont;
18761 int ncoeffspone;
18762 int ncoeffsnone;
18763 int ncoeffspint;
18764 int ncoeffsnint;
18765 int ncoeffspfrac;
18766 int ncoeffsnfrac;
18767 int i;
18768
18769 assert(scip != NULL);
18770 assert(cons != NULL);
18771 assert(upgdcons != NULL);
18772
18773 *upgdcons = NULL;
18774
18775 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18776 if( SCIPconsIsModifiable(cons) )
18777 return SCIP_OKAY;
18778
18779 /* check for upgradability */
18780 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18781 return SCIP_OKAY;
18782
18783 /* get the constraint handler and check, if it's really a linear constraint */
18784 conshdlr = SCIPconsGetHdlr(cons);
18785 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18786 {
18787 SCIPerrorMessage("constraint is not linear\n");
18788 return SCIP_INVALIDDATA;
18789 }
18790
18791 /* get constraint handler data and constraint data */
18792 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18793 assert(conshdlrdata != NULL);
18794 consdata = SCIPconsGetData(cons);
18795 assert(consdata != NULL);
18796
18797 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18798 if( consdata->upgraded )
18799 return SCIP_OKAY;
18800
18801 /* check, if the constraint is already stored as LP row */
18802 if( consdata->row != NULL )
18803 {
18804 if( SCIProwIsInLP(consdata->row) )
18805 {
18806 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18807 return SCIP_INVALIDDATA;
18808 }
18809 else
18810 {
18811 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18812 }
18813 }
18814
18815 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18816
18817 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18818 * skipped and we hope that the infeasibility gets detected later again.
18819 *
18820 * TODO: do we want to try to upgrade the constraint anyway?
18821 *
18822 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18823 * proven to be infeasible.
18824 */
18825 if( infeasible ) /*lint !e774*/
18826 return SCIP_OKAY;
18827
18828 /* tighten sides */
18829 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18830
18831 if( infeasible ) /*lint !e774*/
18832 return SCIP_OKAY;
18833
18834 /*
18835 * calculate some statistics on linear constraint
18836 */
18837
18838 nposbin = 0;
18839 nnegbin = 0;
18840 nposint = 0;
18841 nnegint = 0;
18842 nposimpl = 0;
18843 nnegimpl = 0;
18844 nposimplbin = 0;
18845 nnegimplbin = 0;
18846 nposcont = 0;
18847 nnegcont = 0;
18848 ncoeffspone = 0;
18849 ncoeffsnone = 0;
18850 ncoeffspint = 0;
18851 ncoeffsnint = 0;
18852 ncoeffspfrac = 0;
18853 ncoeffsnfrac = 0;
18854 integral = TRUE;
18855 poscoeffsum = 0.0;
18856 negcoeffsum = 0.0;
18857
18858 for( i = 0; i < consdata->nvars; ++i )
18859 {
18860 var = consdata->vars[i];
18861 val = consdata->vals[i];
18862 lb = SCIPvarGetLbLocal(var);
18863 ub = SCIPvarGetUbLocal(var);
18864 assert(!SCIPisZero(scip, val));
18865
18866 switch( SCIPvarGetType(var) )
18867 {
18869 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18870 integral = integral && SCIPisIntegral(scip, val);
18871 if( val >= 0.0 )
18872 nposbin++;
18873 else
18874 nnegbin++;
18875 break;
18877 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18878 integral = integral && SCIPisIntegral(scip, val);
18879 if( val >= 0.0 )
18880 nposint++;
18881 else
18882 nnegint++;
18883 break;
18885 if( SCIPvarIsBinary(var) )
18886 {
18887 if( val >= 0.0 )
18888 nposimplbin++;
18889 else
18890 nnegimplbin++;
18891 }
18892 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18893 integral = integral && SCIPisIntegral(scip, val);
18894 if( val >= 0.0 )
18895 nposimpl++;
18896 else
18897 nnegimpl++;
18898 break;
18900 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18901 if( val >= 0.0 )
18902 nposcont++;
18903 else
18904 nnegcont++;
18905 break;
18906 default:
18907 SCIPerrorMessage("unknown variable type\n");
18908 return SCIP_INVALIDDATA;
18909 }
18910 if( SCIPisEQ(scip, val, 1.0) )
18911 ncoeffspone++;
18912 else if( SCIPisEQ(scip, val, -1.0) )
18913 ncoeffsnone++;
18914 else if( SCIPisIntegral(scip, val) )
18915 {
18916 if( SCIPisPositive(scip, val) )
18917 ncoeffspint++;
18918 else
18919 ncoeffsnint++;
18920 }
18921 else
18922 {
18923 if( SCIPisPositive(scip, val) )
18924 ncoeffspfrac++;
18925 else
18926 ncoeffsnfrac++;
18927 }
18928 if( SCIPisPositive(scip, val) )
18929 poscoeffsum += val;
18930 else
18931 negcoeffsum += val;
18932 }
18933
18934 /*
18935 * call the upgrading methods
18936 */
18937
18938 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18939 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18940 SCIPdebugMsg(scip, " +bin=%d -bin=%d +int=%d -int=%d +impl=%d -impl=%d +cont=%d -cont=%d +1=%d -1=%d +I=%d -I=%d +F=%d -F=%d possum=%.15g negsum=%.15g integral=%u\n",
18941 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18942 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18943 poscoeffsum, negcoeffsum, integral);
18944
18945 /* try all upgrading methods in priority order in case the upgrading step is enable */
18946 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18947 {
18948 if( conshdlrdata->linconsupgrades[i]->active )
18949 {
18950 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18951 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18952 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18953 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18954 poscoeffsum, negcoeffsum, integral,
18955 upgdcons) );
18956 }
18957 }
18958
18959#ifdef SCIP_DEBUG
18960 if( *upgdcons != NULL )
18961 {
18963 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18964 SCIPdebugPrintCons(scip, *upgdcons, NULL);
18965 }
18966#endif
18967
18968 return SCIP_OKAY; /*lint !e438*/
18969}
18970
18971/** cleans up (multi-)aggregations and fixings from linear constraints */
18973 SCIP* scip, /**< SCIP data structure */
18974 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18975 SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
18976 )
18977{
18978 SCIP_CONSHDLR* conshdlr;
18979 SCIP_CONS** conss;
18980 int nconss;
18981 int i;
18982
18983 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18984 if( conshdlr == NULL )
18985 return SCIP_OKAY;
18986
18987 assert(infeasible != NULL);
18988 *infeasible = FALSE;
18989
18990 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
18991 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
18992
18993 for( i = 0; i < nconss; ++i )
18994 {
18995 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
18996
18997 if( *infeasible )
18998 break;
18999 }
19000
19001 return SCIP_OKAY;
19002}
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:9487
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:9599
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:9545
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9431
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:262
#define SCIP_MAXSTRLEN
Definition: def.h:283
#define COPYSIGN
Definition: def.h:253
#define SCIP_Longint
Definition: def.h:157
#define SCIP_MAXTREEDEPTH
Definition: def.h:311
#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:238
#define MAX3(x, y, z)
Definition: def.h:242
#define SCIP_Real
Definition: def.h:172
#define ABS(x)
Definition: def.h:230
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:234
#define SCIP_CALL_ABORT(x)
Definition: def.h:348
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define MIN3(x, y, z)
Definition: def.h:246
#define SCIPABORT()
Definition: def.h:341
#define REALABS(x)
Definition: def.h:196
#define EPSGT(x, y, eps)
Definition: def.h:200
#define SCIP_CALL(x)
Definition: def.h:369
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:2070
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:9122
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9374
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9825
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition: misc.c:9395
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11213
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:10397
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:435
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:4675
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:4246
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4632
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:5159
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4655
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4216
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:940
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:4236
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:4689
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:4612
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:8263
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:8243
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8492
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8253
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8402
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8684
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip_cons.c:1296
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8442
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8532
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8432
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8362
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8542
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8582
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip_cons.c:1271
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition: scip_cons.c:1321
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition: cons.c:8626
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8422
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2042
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8294
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:997
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8452
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8472
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8592
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8233
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8572
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1812
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2014
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8482
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip_cons.c:1524
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8512
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip_cons.c:1371
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition: scip_cons.c:1346
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8412
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8502
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:111
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:361
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:407
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:3871
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1460
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1552
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1438
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:3881
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:84
#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:1965
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:8127
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition: cons.c:8095
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17440
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1587
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:1426
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1705
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2216
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2171
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1566
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17354
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1611
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17552
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_lp.c:1731
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17341
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2148
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:17638
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:12792
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17658
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:17900
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18208
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17912
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17766
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17617
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:7026
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:17556
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3353
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip_var.c:8658
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18162
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8691
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17579
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:8494
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:5729
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17944
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:17602
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:18106
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17776
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:17786
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17437
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:8628
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18698
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:17628
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8281
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1693
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17876
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17864
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:6885
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17648
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18152
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17592
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17724
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:17566
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18096
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8381
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:11960
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:18688
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:8722
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:17888
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:5540
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10878
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10867
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:5739
static const char * paramname[]
Definition: lpi_msk.c:5171
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:61
@ 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