Scippy

SCIP

Solving Constraint Integer Programs

cons_linear.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file cons_linear.c
26 * @ingroup DEFPLUGINS_CONS
27 * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Marc Pfetsch
31 * @author Kati Wolter
32 * @author Michael Winkler
33 * @author Gerald Gamrath
34 * @author Domenico Salvagnin
35 *
36 * Linear constraints are separated with a high priority, because they are easy
37 * to separate. Instead of using the global cut pool, the same effect can be
38 * implemented by adding linear constraints to the root node, such that they are
39 * separated each time, the linear constraints are separated. A constraint
40 * handler, which generates linear constraints in this way should have a lower
41 * separation priority than the linear constraint handler, and it should have a
42 * separation frequency that is a multiple of the frequency of the linear
43 * constraint handler. In this way, it can be avoided to separate the same cut
44 * twice, because if a separation run of the handler is always preceded by a
45 * separation of the linear constraints, the priorily added constraints are
46 * always satisfied.
47 *
48 * Linear constraints are enforced and checked with a very low priority. Checking
49 * of (many) linear constraints is much more involved than checking the solution
50 * values for integrality. Because we are separating the linear constraints quite
51 * often, it is only necessary to enforce them for integral solutions. A constraint
52 * handler which generates pool cuts in its enforcing method should have an
53 * enforcing priority smaller than that of the linear constraint handler to avoid
54 * regenerating constraints which already exist.
55 */
56
57/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
58
60#include "scip/cons_nonlinear.h"
61#include "scip/cons_knapsack.h"
62#include "scip/cons_linear.h"
63#include "scip/debug.h"
64#include "scip/pub_conflict.h"
65#include "scip/pub_cons.h"
66#include "scip/pub_event.h"
67#include "scip/pub_expr.h"
68#include "scip/pub_lp.h"
69#include "scip/pub_message.h"
70#include "scip/pub_misc.h"
71#include "scip/pub_misc_sort.h"
72#include "scip/pub_var.h"
73#include "scip/scip_branch.h"
74#include "scip/scip_conflict.h"
75#include "scip/scip_cons.h"
76#include "scip/scip_copy.h"
77#include "scip/scip_cut.h"
78#include "scip/scip_event.h"
79#include "scip/scip_general.h"
80#include "scip/scip_lp.h"
81#include "scip/scip_mem.h"
82#include "scip/scip_message.h"
83#include "scip/scip_numerics.h"
84#include "scip/scip_param.h"
85#include "scip/scip_prob.h"
86#include "scip/scip_probing.h"
87#include "scip/scip_sol.h"
89#include "scip/scip_tree.h"
90#include "scip/scip_var.h"
91#include "scip/symmetry_graph.h"
93#include "scip/dbldblarith.h"
94
95
96#define CONSHDLR_NAME "linear"
97#define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
98#define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
99#define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
100#define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
101#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
102#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
103#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
104 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
105#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
106#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
107#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
108#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
109
110#define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
111#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
112
113#define EVENTHDLR_NAME "linear"
114#define EVENTHDLR_DESC "bound change event handler for linear constraints"
115
116#define CONFLICTHDLR_NAME "linear"
117#define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
118#define CONFLICTHDLR_PRIORITY -1000000
119
120#define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
121#define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
122#define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
123#define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
124#define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
125#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
126#define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
127#define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
128#define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
129 * comparison round */
130#define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
131 * propagation? */
132#define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
133 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
134#define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
135 * (0.0: disable constraint aggregation) */
136#define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
137 * (faster, but numerically less stable) */
138#define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
139 * to best node's dual bound for separating knapsack cardinality cuts */
140#define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
141 * the ones with non-zero dual value? */
142#define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
143#define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
144#define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
145#define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
146#define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
147 * constraints using the cheapest variable? */
148#define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
149 * function defining an upper bound and prevent these constraints from
150 * entering the LP */
151#define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
152 * function defining a lower bound and prevent these constraints from
153 * entering the LP */
154#define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
155 * objective function */
156#define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
157#define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
158#define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
159#define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
160
161#define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
162 * removed afterwards? */
163#define DEFAULT_MAXMULTAGGRQUOT 1e+03 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
164#define DEFAULT_MAXDUALMULTAGGRQUOT 1e+20 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
165#define DEFAULT_EXTRACTCLIQUES TRUE /**< should cliques be extracted? */
166
167#define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
168#define MAXSCALEDCOEF 0 /**< maximal coefficient value after scaling */
169#define MAXSCALEDCOEFINTEGER 0 /**< maximal coefficient value after scaling if all variables are of integral
170 * type
171 */
172#define MAXACTVAL 1e+09 /**< maximal absolute value of full and partial activities such that
173 * redundancy-based simplifications are allowed to be applied
174 */
175
176#define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
177#define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
178
179
180#define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of expressions constraints */
181
182/* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
183 * maybe in fullDualPresolve(), see convertLongEquality()
184 */
185
186
187/** constraint data for linear constraints */
188struct SCIP_ConsData
189{
190 SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
191 SCIP_Real rhs; /**< right hand side of row */
192 SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
193 SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
194 QUAD_MEMBER(SCIP_Real minactivity); /**< minimal value w.r.t. the variable's local bounds for the constraint's
195 * activity, ignoring the coefficients contributing with infinite value */
196 QUAD_MEMBER(SCIP_Real maxactivity); /**< maximal value w.r.t. the variable's local bounds for the constraint's
197 * activity, ignoring the coefficients contributing with infinite value */
198 SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
199 * over all contributing values */
200 SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
201 * over all contributing values */
202 QUAD_MEMBER(SCIP_Real glbminactivity); /**< minimal value w.r.t. the variable's global bounds for the constraint's
203 * activity, ignoring the coefficients contributing with infinite value */
204 QUAD_MEMBER(SCIP_Real glbmaxactivity); /**< maximal value w.r.t. the variable's global bounds for the constraint's
205 * activity, ignoring the coefficients contributing with infinite value */
206 SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
207 * over all contributing values */
208 SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
209 * over all contributing values */
210 SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
211 SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
212 uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
213 uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
214 SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
215 SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */
216 SCIP_VAR** vars; /**< variables of constraint entries */
217 SCIP_Real* vals; /**< coefficients of constraint entries */
218 SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
219 int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
220 int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
221 int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
222 int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
223 int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
224 int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
225 int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
226 int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
227 int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
228 int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
229 int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
230 int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
231 int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
232 int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
233 int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
234 int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
235 int varssize; /**< size of the vars- and vals-arrays */
236 int nvars; /**< number of nonzeros in constraint */
237 int nbinvars; /**< the number of binary variables in the constraint, only valid after
238 * sorting in stage >= SCIP_STAGE_INITSOLVE
239 */
240 unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
241 unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
242 * (0: no, 1: yes, 2: with potentially adding artificial constraint */
243 unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
244 unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
245 unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
246 unsigned int validminact:1; /**< is the local minactivity valid? */
247 unsigned int validmaxact:1; /**< is the local maxactivity valid? */
248 unsigned int validglbminact:1; /**< is the global minactivity valid? */
249 unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
250 unsigned int presolved:1; /**< is constraint already presolved? */
251 unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
252 unsigned int validsignature:1; /**< is the bit signature valid? */
253 unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
254 unsigned int normalized:1; /**< is the constraint in normalized form? */
255 unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
256 unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
257 unsigned int indexsorted:1; /**< are the constraint's variables sorted by type and index? */
258 unsigned int merged:1; /**< are the constraint's equal variables already merged? */
259 unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
260 unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
261 unsigned int coefsorted:1; /**< are variables sorted by type and their absolute activity delta? */
262 unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
263 unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
264 unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
265 unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
266 unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
267};
268
269/** event data for bound change event */
270struct SCIP_EventData
271{
272 SCIP_CONS* cons; /**< linear constraint to process the bound change for */
273 int varpos; /**< position of variable in vars array */
274 int filterpos; /**< position of event in variable's event filter */
275};
276
277/** constraint handler data */
278struct SCIP_ConshdlrData
279{
280 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
281 SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
282 SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
283 * (0.0: disable constraint aggregation) */
284 SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
285 * to best node's dual bound for separating knapsack cardinality cuts */
286 SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
287 SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
288 * (faster, but numerically less stable) */
289 int linconsupgradessize;/**< size of linconsupgrade array */
290 int nlinconsupgrades; /**< number of linear constraint upgrade methods */
291 int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
292 int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
293 int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
294 int maxsepacuts; /**< maximal number of cuts separated per separation round */
295 int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
296 int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
297 int naddconss; /**< number of added constraints */
298 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
299 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
300 SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
301 * the ones with non-zero dual value? */
302 SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
303 SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
304 SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
305 SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
306 SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
307 * constraints using the cheapest variable? */
308 SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
309 SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
310 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
311 SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
312 * function defining an upper bound and prevent these constraints from
313 * entering the LP */
314 SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
315 * function defining a lower bound and prevent these constraints from
316 * entering the LP */
317 SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
318 * the objective function */
319 SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
320 * infeasibility, and extract sub-constraints from ranged rows and
321 * equations */
322 SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
323 int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
324 int rangedrowfreq; /**< frequency for applying ranged row propagation */
325 SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
326 * removed afterwards? */
327 SCIP_Real maxmultaggrquot; /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation */
328 SCIP_Real maxdualmultaggrquot;/**< maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation */
329 SCIP_Bool extractcliques; /**< should cliques be extracted? */
330};
331
332/** linear constraint update method */
334{
335 SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
336 int priority; /**< priority of upgrading method */
337 SCIP_Bool active; /**< is upgrading enabled */
338};
339
340
341/*
342 * Propagation rules
343 */
344
346{
347 PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
348 * variable due to the right hand side of the inequality */
349 PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
350 * variable due to the left hand side of the inequality */
351 PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
352 * single variable in this reanged row */
353 PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
355typedef enum Proprule PROPRULE;
356
357/** inference information */
358struct InferInfo
359{
360 union
361 {
362 struct
363 {
364 unsigned int proprule:8; /**< propagation rule that was applied */
365 unsigned int pos:24; /**< variable position, the propagation rule was applied at */
366 } asbits;
367 int asint; /**< inference information as a single int value */
368 } val;
369};
370typedef struct InferInfo INFERINFO;
371
372/** converts an integer into an inference information */
373static
375 int i /**< integer to convert */
376 )
377{
378 INFERINFO inferinfo;
379
380 inferinfo.val.asint = i;
381
382 return inferinfo;
383}
384
385/** converts an inference information into an int */
386static
388 INFERINFO inferinfo /**< inference information to convert */
389 )
390{
391 return inferinfo.val.asint;
392}
393
394/** returns the propagation rule stored in the inference information */
395static
397 INFERINFO inferinfo /**< inference information to convert */
398 )
399{
400 return (int) inferinfo.val.asbits.proprule;
401}
402
403/** returns the position stored in the inference information */
404static
406 INFERINFO inferinfo /**< inference information to convert */
407 )
408{
409 return (int) inferinfo.val.asbits.pos;
410}
411
412/** constructs an inference information out of a propagation rule and a position number */
413static
415 PROPRULE proprule, /**< propagation rule that deduced the value */
416 int pos /**< variable position, the propagation rule was applied at */
417 )
418{
419 INFERINFO inferinfo;
420
421 assert(pos >= 0);
422 /* in the inferinfo struct only 24 bits for 'pos' are reserved */
423 assert(pos < (1<<24));
424
425 inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
426 inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
427
428 return inferinfo;
429}
430
431/** constructs an inference information out of a propagation rule and a position number, returns info as int */
432static
434 PROPRULE proprule, /**< propagation rule that deduced the value */
435 int pos /**< variable position, the propagation rule was applied at */
436 )
437{
438 return inferInfoToInt(getInferInfo(proprule, pos));
439}
440
441
442/*
443 * memory growing methods for dynamically allocated arrays
444 */
445
446/** ensures, that linconsupgrades array can store at least num entries */
447static
449 SCIP* scip, /**< SCIP data structure */
450 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
451 int num /**< minimum number of entries to store */
452 )
453{
454 assert(scip != NULL);
455 assert(conshdlrdata != NULL);
456 assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
457
458 if( num > conshdlrdata->linconsupgradessize )
459 {
460 int newsize;
461
462 newsize = SCIPcalcMemGrowSize(scip, num);
463 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
464 conshdlrdata->linconsupgradessize = newsize;
465 }
466 assert(num <= conshdlrdata->linconsupgradessize);
467
468 return SCIP_OKAY;
469}
470
471/** ensures, that vars and vals arrays can store at least num entries */
472static
474 SCIP* scip, /**< SCIP data structure */
475 SCIP_CONSDATA* consdata, /**< linear constraint data */
476 int num /**< minimum number of entries to store */
477 )
478{
479 assert(scip != NULL);
480 assert(consdata != NULL);
481 assert(consdata->nvars <= consdata->varssize);
482
483 if( num > consdata->varssize )
484 {
485 int newsize;
486
487 newsize = SCIPcalcMemGrowSize(scip, num);
488 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
489 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
490 if( consdata->eventdata != NULL )
491 {
492 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
493 }
494 consdata->varssize = newsize;
495 }
496 assert(num <= consdata->varssize);
497
498 return SCIP_OKAY;
499}
500
501
502/*
503 * local methods for managing linear constraint update methods
504 */
505
506/** creates a linear constraint upgrade data object */
507static
509 SCIP* scip, /**< SCIP data structure */
510 SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
511 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
512 int priority /**< priority of upgrading method */
513 )
514{
515 assert(scip != NULL);
516 assert(linconsupgrade != NULL);
517 assert(linconsupgd != NULL);
518
519 SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
520 (*linconsupgrade)->linconsupgd = linconsupgd;
521 (*linconsupgrade)->priority = priority;
522 (*linconsupgrade)->active = TRUE;
523
524 return SCIP_OKAY;
525}
526
527/** frees a linear constraint upgrade data object */
528static
530 SCIP* scip, /**< SCIP data structure */
531 SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
532 )
533{
534 assert(scip != NULL);
535 assert(linconsupgrade != NULL);
536 assert(*linconsupgrade != NULL);
537
538 SCIPfreeBlockMemory(scip, linconsupgrade);
539}
540
541/** creates constraint handler data for linear constraint handler */
542static
544 SCIP* scip, /**< SCIP data structure */
545 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
546 SCIP_EVENTHDLR* eventhdlr /**< event handler */
547 )
548{
549 assert(scip != NULL);
550 assert(conshdlrdata != NULL);
551 assert(eventhdlr != NULL);
552
553 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
554 (*conshdlrdata)->linconsupgrades = NULL;
555 (*conshdlrdata)->linconsupgradessize = 0;
556 (*conshdlrdata)->nlinconsupgrades = 0;
557 (*conshdlrdata)->naddconss = 0;
558
559 /* set event handler for updating linear constraint activity bounds */
560 (*conshdlrdata)->eventhdlr = eventhdlr;
561
562 return SCIP_OKAY;
563}
564
565/** frees constraint handler data for linear constraint handler */
566static
568 SCIP* scip, /**< SCIP data structure */
569 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
570 )
571{
572 int i;
573
574 assert(scip != NULL);
575 assert(conshdlrdata != NULL);
576 assert(*conshdlrdata != NULL);
577
578 for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
579 {
580 linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
581 }
582 SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
583
584 SCIPfreeBlockMemory(scip, conshdlrdata);
585}
586
587/** creates a linear constraint upgrade data object */
588static
590 SCIP* scip, /**< SCIP data structure */
591 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
592 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
593 const char* conshdlrname /**< name of the constraint handler */
594 )
595{
596 int i;
597
598 assert(scip != NULL);
599 assert(conshdlrdata != NULL);
600 assert(linconsupgd != NULL);
601 assert(conshdlrname != NULL);
602
603 for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
604 {
605 if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
606 {
607#ifdef SCIP_DEBUG
608 SCIPwarningMessage(scip, "Try to add already known upgrade message for constraint handler %s.\n", conshdlrname);
609#endif
610 return TRUE;
611 }
612 }
613
614 return FALSE;
615}
616
617/** adds a linear constraint update method to the constraint handler's data */
618static
620 SCIP* scip, /**< SCIP data structure */
621 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
622 SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
623 )
624{
625 int i;
626
627 assert(scip != NULL);
628 assert(conshdlrdata != NULL);
629 assert(linconsupgrade != NULL);
630
631 SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
632
633 for( i = conshdlrdata->nlinconsupgrades;
634 i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
635 {
636 conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
637 }
638 assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
639 conshdlrdata->linconsupgrades[i] = linconsupgrade;
640 conshdlrdata->nlinconsupgrades++;
641
642 return SCIP_OKAY;
643}
644
645/*
646 * local methods
647 */
648
649/** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
650static
652 SCIP* scip, /**< SCIP data structure */
653 SCIP_CONS* cons, /**< linear constraint */
654 SCIP_VAR* var, /**< variable of constraint entry */
655 SCIP_Real val /**< coefficient of constraint entry */
656 )
657{
658 SCIP_CONSDATA* consdata;
659
660 assert(scip != NULL);
661 assert(cons != NULL);
662 assert(var != NULL);
663
664 consdata = SCIPconsGetData(cons);
665 assert(consdata != NULL);
666 assert(!SCIPisZero(scip, val));
667
668 if( val < 0.0 )
669 {
670 SCIP_CALL( SCIPlockVarCons(scip, var, cons,
671 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
672 }
673 else
674 {
675 SCIP_CALL( SCIPlockVarCons(scip, var, cons,
676 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
677 }
678
679 return SCIP_OKAY;
680}
681
682/** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
683static
685 SCIP* scip, /**< SCIP data structure */
686 SCIP_CONS* cons, /**< linear constraint */
687 SCIP_VAR* var, /**< variable of constraint entry */
688 SCIP_Real val /**< coefficient of constraint entry */
689 )
690{
691 SCIP_CONSDATA* consdata;
692
693 assert(scip != NULL);
694 assert(cons != NULL);
695 assert(var != NULL);
696
697 consdata = SCIPconsGetData(cons);
698 assert(consdata != NULL);
699 assert(!SCIPisZero(scip, val));
700
701 if( val < 0.0 )
702 {
703 SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
704 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
705 }
706 else
707 {
708 SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
709 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
710 }
711
712 return SCIP_OKAY;
713}
714
715/** creates event data for variable at given position, and catches events */
716/**! [SnippetDebugAssertions] */
717static
719 SCIP* scip, /**< SCIP data structure */
720 SCIP_CONS* cons, /**< linear constraint */
721 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
722 int pos /**< array position of variable to catch bound change events for */
723 )
724{
725 SCIP_CONSDATA* consdata;
726 assert(scip != NULL);
727 assert(cons != NULL);
728 assert(eventhdlr != NULL);
729
730 consdata = SCIPconsGetData(cons);
731 assert(consdata != NULL);
732
733 assert(0 <= pos && pos < consdata->nvars);
734 assert(consdata->vars != NULL);
735 assert(consdata->vars[pos] != NULL);
736 assert(SCIPvarIsTransformed(consdata->vars[pos]));
737 assert(consdata->eventdata != NULL);
738 assert(consdata->eventdata[pos] == NULL);
739
740 SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
741 consdata->eventdata[pos]->cons = cons;
742 consdata->eventdata[pos]->varpos = pos;
743
744 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
747 eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
748
749 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(consdata->vars[pos]);
750
751 return SCIP_OKAY;
752}
753/**! [SnippetDebugAssertions] */
754
755/** deletes event data for variable at given position, and drops events */
756static
758 SCIP* scip, /**< SCIP data structure */
759 SCIP_CONS* cons, /**< linear constraint */
760 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
761 int pos /**< array position of variable to catch bound change events for */
762 )
763{
764 SCIP_CONSDATA* consdata;
765 assert(scip != NULL);
766 assert(cons != NULL);
767 assert(eventhdlr != NULL);
768
769 consdata = SCIPconsGetData(cons);
770 assert(consdata != NULL);
771
772 assert(0 <= pos && pos < consdata->nvars);
773 assert(consdata->vars[pos] != NULL);
774 assert(consdata->eventdata != NULL);
775 assert(consdata->eventdata[pos] != NULL);
776 assert(consdata->eventdata[pos]->cons == cons);
777 assert(consdata->eventdata[pos]->varpos == pos);
778
779 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
782 eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
783
784 SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
785
786 return SCIP_OKAY;
787}
788
789/** catches bound change events for all variables in transformed linear constraint */
790static
792 SCIP* scip, /**< SCIP data structure */
793 SCIP_CONS* cons, /**< linear constraint */
794 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
795 )
796{
797 SCIP_CONSDATA* consdata;
798 int i;
799
800 assert(scip != NULL);
801 assert(cons != NULL);
802
803 consdata = SCIPconsGetData(cons);
804 assert(consdata != NULL);
805 assert(consdata->eventdata == NULL);
806
807 /* allocate eventdata array */
808 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
809 assert(consdata->eventdata != NULL);
810 BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
811
812 /* catch event for every single variable */
813 for( i = 0; i < consdata->nvars; ++i )
814 {
815 SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
816 }
817
818 return SCIP_OKAY;
819}
820
821/** drops bound change events for all variables in transformed linear constraint */
822static
824 SCIP* scip, /**< SCIP data structure */
825 SCIP_CONS* cons, /**< linear constraint */
826 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
827 )
828{
829 SCIP_CONSDATA* consdata;
830 int i;
831
832 assert(scip != NULL);
833 assert(cons != NULL);
834
835 consdata = SCIPconsGetData(cons);
836 assert(consdata != NULL);
837 assert(consdata->eventdata != NULL);
838
839 /* drop event of every single variable */
840 for( i = consdata->nvars - 1; i >= 0; --i )
841 {
842 SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
843 }
844
845 /* free eventdata array */
846 SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
847 assert(consdata->eventdata == NULL);
848
849 return SCIP_OKAY;
850}
851
852/** creates a linear constraint data */
853static
855 SCIP* scip, /**< SCIP data structure */
856 SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
857 int nvars, /**< number of nonzeros in the constraint */
858 SCIP_VAR** vars, /**< array with variables of constraint entries */
859 SCIP_Real* vals, /**< array with coefficients of constraint entries */
860 SCIP_Real lhs, /**< left hand side of row */
861 SCIP_Real rhs /**< right hand side of row */
862 )
863{
864 int v;
865 SCIP_Real constant;
866
867 assert(scip != NULL);
868 assert(consdata != NULL);
869 assert(nvars == 0 || vars != NULL);
870 assert(nvars == 0 || vals != NULL);
871
872 if( SCIPisInfinity(scip, rhs) )
873 rhs = SCIPinfinity(scip);
874 else if( SCIPisInfinity(scip, -rhs) )
875 rhs = -SCIPinfinity(scip);
876
877 if( SCIPisInfinity(scip, -lhs) )
878 lhs = -SCIPinfinity(scip);
879 else if( SCIPisInfinity(scip, lhs) )
880 lhs = SCIPinfinity(scip);
881
882 if( SCIPisGT(scip, lhs, rhs) )
883 {
884 SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
885 SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
886 }
887
888 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
889
890 (*consdata)->varssize = 0;
891 (*consdata)->nvars = nvars;
892 (*consdata)->hascontvar = FALSE;
893 (*consdata)->hasnonbinvar = FALSE;
894 (*consdata)->hasnonbinvalid = TRUE;
895 (*consdata)->vars = NULL;
896 (*consdata)->vals = NULL;
897
898 constant = 0.0;
899 if( nvars > 0 )
900 {
901 SCIP_VAR** varsbuffer;
902 SCIP_Real* valsbuffer;
903
904 /* copy variables into temporary buffer */
905 SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
906 SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
907 nvars = 0;
908
909 /* loop over variables and sort out fixed ones */
910 for( v = 0; v < (*consdata)->nvars; ++v )
911 {
912 SCIP_VAR* var;
913 SCIP_Real val;
914
915 var = vars[v];
916 val = vals[v];
917
918 assert(var != NULL);
919 if( !SCIPisZero(scip, val) )
920 {
921 /* treat fixed variable as a constant if problem compression is enabled */
923 {
924 constant += SCIPvarGetLbGlobal(var) * val;
925 }
926 else
927 {
928 varsbuffer[nvars] = var;
929 valsbuffer[nvars] = val;
930 ++nvars;
931
932 /* update hascontvar and hasnonbinvar flags */
933 if( !(*consdata)->hascontvar )
934 {
935 SCIP_VARTYPE vartype = SCIPvarGetType(var);
936
937 if( vartype != SCIP_VARTYPE_BINARY )
938 {
939 (*consdata)->hasnonbinvar = TRUE;
940
941 if( vartype == SCIP_VARTYPE_CONTINUOUS )
942 (*consdata)->hascontvar = TRUE;
943 }
944 }
945 }
946 }
947 }
948 (*consdata)->nvars = nvars;
949
950 if( nvars > 0 )
951 {
952 /* copy the possibly reduced buffer arrays into block */
953 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, nvars) );
954 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, nvars) );
955 (*consdata)->varssize = nvars;
956 }
957 /* free temporary buffer */
958 SCIPfreeBufferArray(scip, &valsbuffer);
959 SCIPfreeBufferArray(scip, &varsbuffer);
960 }
961
962 (*consdata)->eventdata = NULL;
963
964 /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
965 if( !SCIPisZero(scip, constant) )
966 {
967 if( !SCIPisInfinity(scip, REALABS(lhs)) )
968 lhs -= constant;
969
970 if( !SCIPisInfinity(scip, REALABS(rhs)) )
971 rhs -= constant;
972 }
973
974 (*consdata)->row = NULL;
975 (*consdata)->nlrow = NULL;
976 (*consdata)->lhs = lhs;
977 (*consdata)->rhs = rhs;
978 (*consdata)->maxabsval = SCIP_INVALID;
979 (*consdata)->minabsval = SCIP_INVALID;
980 QUAD_ASSIGN((*consdata)->minactivity, SCIP_INVALID);
981 QUAD_ASSIGN((*consdata)->maxactivity, SCIP_INVALID);
982 (*consdata)->lastminactivity = SCIP_INVALID;
983 (*consdata)->lastmaxactivity = SCIP_INVALID;
984 (*consdata)->maxactdelta = SCIP_INVALID;
985 (*consdata)->maxactdeltavar = NULL;
986 (*consdata)->minactivityneginf = -1;
987 (*consdata)->minactivityposinf = -1;
988 (*consdata)->maxactivityneginf = -1;
989 (*consdata)->maxactivityposinf = -1;
990 (*consdata)->minactivityneghuge = -1;
991 (*consdata)->minactivityposhuge = -1;
992 (*consdata)->maxactivityneghuge = -1;
993 (*consdata)->maxactivityposhuge = -1;
994 QUAD_ASSIGN((*consdata)->glbminactivity, SCIP_INVALID);
995 QUAD_ASSIGN((*consdata)->glbmaxactivity, SCIP_INVALID);
996 (*consdata)->lastglbminactivity = SCIP_INVALID;
997 (*consdata)->lastglbmaxactivity = SCIP_INVALID;
998 (*consdata)->glbminactivityneginf = -1;
999 (*consdata)->glbminactivityposinf = -1;
1000 (*consdata)->glbmaxactivityneginf = -1;
1001 (*consdata)->glbmaxactivityposinf = -1;
1002 (*consdata)->glbminactivityneghuge = -1;
1003 (*consdata)->glbminactivityposhuge = -1;
1004 (*consdata)->glbmaxactivityneghuge = -1;
1005 (*consdata)->glbmaxactivityposhuge = -1;
1006 (*consdata)->possignature = 0;
1007 (*consdata)->negsignature = 0;
1008 (*consdata)->validmaxabsval = FALSE;
1009 (*consdata)->validminabsval = FALSE;
1010 (*consdata)->validactivities = FALSE;
1011 (*consdata)->validminact = FALSE;
1012 (*consdata)->validmaxact = FALSE;
1013 (*consdata)->validglbminact = FALSE;
1014 (*consdata)->validglbmaxact = FALSE;
1015 (*consdata)->boundstightened = 0;
1016 (*consdata)->presolved = FALSE;
1017 (*consdata)->removedfixings = FALSE;
1018 (*consdata)->validsignature = FALSE;
1019 (*consdata)->changed = TRUE;
1020 (*consdata)->normalized = FALSE;
1021 (*consdata)->upgradetried = FALSE;
1022 (*consdata)->upgraded = FALSE;
1023 (*consdata)->indexsorted = (nvars <= 1);
1024 (*consdata)->merged = (nvars <= 1);
1025 (*consdata)->cliquesadded = FALSE;
1026 (*consdata)->implsadded = FALSE;
1027 (*consdata)->coefsorted = FALSE;
1028 (*consdata)->nbinvars = -1;
1029 (*consdata)->varsdeleted = FALSE;
1030 (*consdata)->rangedrowpropagated = 0;
1031 (*consdata)->checkabsolute = FALSE;
1032
1033 if( SCIPisTransformed(scip) )
1034 {
1035 /* get transformed variables */
1036 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1037 }
1038
1039 /* capture variables */
1040 for( v = 0; v < (*consdata)->nvars; v++ )
1041 {
1042 /* likely implies a deleted variable */
1043 if( (*consdata)->vars[v] == NULL )
1044 {
1045 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1046 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1047 SCIPfreeBlockMemory(scip, consdata);
1048 return SCIP_INVALIDDATA;
1049 }
1050
1051 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1052 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1053 }
1054
1055 return SCIP_OKAY;
1056}
1057
1058/** frees a linear constraint data */
1059static
1061 SCIP* scip, /**< SCIP data structure */
1062 SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1063 )
1064{
1065 int v;
1066
1067 assert(scip != NULL);
1068 assert(consdata != NULL);
1069 assert(*consdata != NULL);
1070 assert((*consdata)->varssize >= 0);
1071
1072 /* release the row */
1073 if( (*consdata)->row != NULL )
1074 {
1075 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1076 }
1077
1078 /* release the nlrow */
1079 if( (*consdata)->nlrow != NULL )
1080 {
1081 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
1082 }
1083
1084 /* release variables */
1085 for( v = 0; v < (*consdata)->nvars; v++ )
1086 {
1087 assert((*consdata)->vars[v] != NULL);
1088 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1089 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1090 }
1091
1092 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1093 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1094 SCIPfreeBlockMemory(scip, consdata);
1095
1096 return SCIP_OKAY;
1097}
1098
1099/** prints linear constraint in CIP format to file stream */
1100static
1102 SCIP* scip, /**< SCIP data structure */
1103 SCIP_CONSDATA* consdata, /**< linear constraint data */
1104 FILE* file /**< output file (or NULL for standard output) */
1105 )
1106{
1107 assert(scip != NULL);
1108 assert(consdata != NULL);
1109
1110 /* print left hand side for ranged rows */
1111 if( !SCIPisInfinity(scip, -consdata->lhs)
1112 && !SCIPisInfinity(scip, consdata->rhs)
1113 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1114 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1115
1116 /* print coefficients and variables */
1117 if( consdata->nvars == 0 )
1118 SCIPinfoMessage(scip, file, "0");
1119 else
1120 {
1121 /* post linear sum of the linear constraint */
1122 SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1123 }
1124
1125 /* print right hand side */
1126 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1127 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1128 else if( !SCIPisInfinity(scip, consdata->rhs) )
1129 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1130 else if( !SCIPisInfinity(scip, -consdata->lhs) )
1131 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1132 else
1133 SCIPinfoMessage(scip, file, " [free]");
1134
1135 return SCIP_OKAY;
1136}
1137
1138/** prints linear constraint and contained solution values of variables to file stream */
1139static
1141 SCIP* scip, /**< SCIP data structure */
1142 SCIP_CONS* cons, /**< linear constraint */
1143 SCIP_SOL* sol, /**< solution to print */
1144 FILE* file /**< output file (or NULL for standard output) */
1145 )
1146{
1147 SCIP_CONSDATA* consdata;
1148
1149 assert(scip != NULL);
1150 assert(cons != NULL);
1151
1152 consdata = SCIPconsGetData(cons);
1153 assert(consdata != NULL);
1154
1156
1157 /* print left hand side for ranged rows */
1158 if( !SCIPisInfinity(scip, -consdata->lhs)
1159 && !SCIPisInfinity(scip, consdata->rhs)
1160 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1161 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1162
1163 /* print coefficients and variables */
1164 if( consdata->nvars == 0 )
1165 SCIPinfoMessage(scip, file, "0");
1166 else
1167 {
1168 int v;
1169
1170 /* post linear sum of the linear constraint */
1171 for( v = 0; v < consdata->nvars; ++v )
1172 {
1173 if( consdata->vals != NULL )
1174 {
1175 if( consdata->vals[v] == 1.0 )
1176 {
1177 if( v > 0 )
1178 SCIPinfoMessage(scip, file, " +");
1179 }
1180 else if( consdata->vals[v] == -1.0 )
1181 SCIPinfoMessage(scip, file, " -");
1182 else
1183 SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1184 }
1185 else if( consdata->nvars > 0 )
1186 SCIPinfoMessage(scip, file, " +");
1187
1188 /* print variable name */
1189 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1190
1191 SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1192 }
1193 }
1194
1195 /* print right hand side */
1196 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1197 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1198 else if( !SCIPisInfinity(scip, consdata->rhs) )
1199 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1200 else if( !SCIPisInfinity(scip, -consdata->lhs) )
1201 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1202 else
1203 SCIPinfoMessage(scip, file, " [free]");
1204
1205 SCIPinfoMessage(scip, file, ";\n");
1206
1207 return SCIP_OKAY;
1208}
1209
1210/** invalidates activity bounds, such that they are recalculated in next get */
1211static
1213 SCIP_CONSDATA* consdata /**< linear constraint */
1214 )
1215{
1216 assert(consdata != NULL);
1217
1218 consdata->validactivities = FALSE;
1219 consdata->validminact = FALSE;
1220 consdata->validmaxact = FALSE;
1221 consdata->validglbminact = FALSE;
1222 consdata->validglbmaxact = FALSE;
1223 consdata->validmaxabsval = FALSE;
1224 consdata->validminabsval = FALSE;
1225 consdata->hasnonbinvalid = FALSE;
1226 QUAD_ASSIGN(consdata->minactivity, SCIP_INVALID);
1227 QUAD_ASSIGN(consdata->maxactivity, SCIP_INVALID);
1228 consdata->lastminactivity = SCIP_INVALID;
1229 consdata->lastmaxactivity = SCIP_INVALID;
1230 consdata->maxabsval = SCIP_INVALID;
1231 consdata->minabsval = SCIP_INVALID;
1232 consdata->maxactdelta = SCIP_INVALID;
1233 consdata->maxactdeltavar = NULL;
1234 consdata->minactivityneginf = -1;
1235 consdata->minactivityposinf = -1;
1236 consdata->maxactivityneginf = -1;
1237 consdata->maxactivityposinf = -1;
1238 consdata->minactivityneghuge = -1;
1239 consdata->minactivityposhuge = -1;
1240 consdata->maxactivityneghuge = -1;
1241 consdata->maxactivityposhuge = -1;
1242 QUAD_ASSIGN(consdata->glbminactivity, SCIP_INVALID);
1243 QUAD_ASSIGN(consdata->glbmaxactivity, SCIP_INVALID);
1244 consdata->lastglbminactivity = SCIP_INVALID;
1245 consdata->lastglbmaxactivity = SCIP_INVALID;
1246 consdata->glbminactivityneginf = -1;
1247 consdata->glbminactivityposinf = -1;
1248 consdata->glbmaxactivityneginf = -1;
1249 consdata->glbmaxactivityposinf = -1;
1250 consdata->glbminactivityneghuge = -1;
1251 consdata->glbminactivityposhuge = -1;
1252 consdata->glbmaxactivityneghuge = -1;
1253 consdata->glbmaxactivityposhuge = -1;
1254}
1255
1256/** compute the pseudo activity of a constraint */
1257static
1259 SCIP* scip, /**< SCIP data structure */
1260 SCIP_CONSDATA* consdata /**< linear constraint data */
1261 )
1262{
1263 int i;
1264 int pseudoactivityposinf;
1265 int pseudoactivityneginf;
1266 SCIP_Real pseudoactivity;
1268 SCIP_Real val;
1269
1270 pseudoactivity = 0;
1271 pseudoactivityposinf = 0;
1272 pseudoactivityneginf = 0;
1273
1274 for( i = consdata->nvars - 1; i >= 0; --i )
1275 {
1276 val = consdata->vals[i];
1277 bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1278 if( SCIPisInfinity(scip, bound) )
1279 {
1280 if( val > 0.0 )
1281 pseudoactivityposinf++;
1282 else
1283 pseudoactivityneginf++;
1284 }
1285 else
1286 {
1287 if( SCIPisInfinity(scip, -bound) )
1288 {
1289 if( val > 0.0 )
1290 pseudoactivityneginf++;
1291 else
1292 pseudoactivityposinf++;
1293 }
1294 else
1295 pseudoactivity += val * bound;
1296 }
1297 }
1298
1299 if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1300 return SCIP_INVALID;
1301 else if( pseudoactivityneginf > 0 )
1302 return -SCIPinfinity(scip);
1303 else if( pseudoactivityposinf > 0 )
1304 return SCIPinfinity(scip);
1305
1306 return pseudoactivity;
1307}
1308
1309/** recompute the minactivity of a constraint */
1310static
1312 SCIP* scip, /**< SCIP data structure */
1313 SCIP_CONSDATA* consdata /**< linear constraint data */
1314 )
1315{
1316 int i;
1318
1319 QUAD_ASSIGN(consdata->minactivity, 0.0);
1320
1321 for( i = consdata->nvars - 1; i >= 0; --i )
1322 {
1323 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1325 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1326 SCIPquadprecSumQD(consdata->minactivity, consdata->minactivity, consdata->vals[i] * bound);
1327 }
1328
1329 /* the activity was just computed from scratch and is valid now */
1330 consdata->validminact = TRUE;
1331
1332 /* the activity was just computed from scratch, mark it to be reliable */
1333 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
1334}
1335
1336/** recompute the maxactivity of a constraint */
1337static
1339 SCIP* scip, /**< SCIP data structure */
1340 SCIP_CONSDATA* consdata /**< linear constraint data */
1341 )
1342{
1343 int i;
1345
1346 QUAD_ASSIGN(consdata->maxactivity, 0.0);
1347
1348 for( i = consdata->nvars - 1; i >= 0; --i )
1349 {
1350 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1352 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1353 SCIPquadprecSumQD(consdata->maxactivity, consdata->maxactivity, consdata->vals[i] * bound);
1354 }
1355
1356 /* the activity was just computed from scratch and is valid now */
1357 consdata->validmaxact = TRUE;
1358
1359 /* the activity was just computed from scratch, mark it to be reliable */
1360 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
1361}
1362
1363/** recompute the global minactivity of a constraint */
1364static
1366 SCIP* scip, /**< SCIP data structure */
1367 SCIP_CONSDATA* consdata /**< linear constraint data */
1368 )
1369{
1370 int i;
1372
1373 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
1374
1375 for( i = consdata->nvars - 1; i >= 0; --i )
1376 {
1377 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1379 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1380 SCIPquadprecSumQD(consdata->glbminactivity, consdata->glbminactivity, consdata->vals[i] * bound);
1381 }
1382
1383 /* the activity was just computed from scratch and is valid now */
1384 consdata->validglbminact = TRUE;
1385
1386 /* the activity was just computed from scratch, mark it to be reliable */
1387 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
1388}
1389
1390/** recompute the global maxactivity of a constraint */
1391static
1393 SCIP* scip, /**< SCIP data structure */
1394 SCIP_CONSDATA* consdata /**< linear constraint data */
1395 )
1396{
1397 int i;
1399
1400 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
1401
1402 for( i = consdata->nvars - 1; i >= 0; --i )
1403 {
1404 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1406 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1407 SCIPquadprecSumQD(consdata->glbmaxactivity, consdata->glbmaxactivity, consdata->vals[i] * bound);
1408 }
1409
1410 /* the activity was just computed from scratch and is valid now */
1411 consdata->validglbmaxact = TRUE;
1412
1413 /* the activity was just computed from scratch, mark it to be reliable */
1414 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
1415}
1416
1417/** calculates maximum absolute value of coefficients */
1418static
1420 SCIP_CONSDATA* consdata /**< linear constraint data */
1421 )
1422{
1423 SCIP_Real absval;
1424 int i;
1425
1426 assert(consdata != NULL);
1427 assert(!consdata->validmaxabsval);
1428 assert(consdata->maxabsval >= SCIP_INVALID);
1429
1430 consdata->validmaxabsval = TRUE;
1431 consdata->maxabsval = 0.0;
1432 for( i = 0; i < consdata->nvars; ++i )
1433 {
1434 absval = consdata->vals[i];
1435 absval = REALABS(absval);
1436 if( absval > consdata->maxabsval )
1437 consdata->maxabsval = absval;
1438 }
1439}
1440
1441/** calculates minimum absolute value of coefficients */
1442static
1444 SCIP_CONSDATA* consdata /**< linear constraint data */
1445 )
1446{
1447 SCIP_Real absval;
1448 int i;
1449
1450 assert(consdata != NULL);
1451 assert(!consdata->validminabsval);
1452 assert(consdata->minabsval >= SCIP_INVALID);
1453
1454 consdata->validminabsval = TRUE;
1455
1456 if( consdata->nvars > 0 )
1457 consdata->minabsval = REALABS(consdata->vals[0]);
1458 else
1459 consdata->minabsval = 0.0;
1460
1461 for( i = 1; i < consdata->nvars; ++i )
1462 {
1463 absval = consdata->vals[i];
1464 absval = REALABS(absval);
1465 if( absval < consdata->minabsval )
1466 consdata->minabsval = absval;
1467 }
1468}
1469
1470/** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1471static
1473 SCIP_CONSDATA* consdata /**< linear constraint data */
1474 )
1475{
1476 int v;
1477
1478 assert(!consdata->hasnonbinvalid);
1479 consdata->hasnonbinvar = FALSE;
1480 consdata->hascontvar = FALSE;
1481
1482 for( v = consdata->nvars - 1; v >= 0; --v )
1483 {
1484 SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1485
1486 if( vartype != SCIP_VARTYPE_BINARY )
1487 {
1488 consdata->hasnonbinvar = TRUE;
1489
1490 if( vartype == SCIP_VARTYPE_CONTINUOUS )
1491 {
1492 consdata->hascontvar = TRUE;
1493 break;
1494 }
1495 }
1496 }
1497 assert(consdata->hascontvar || v < 0);
1498
1499 consdata->hasnonbinvalid = TRUE;
1500}
1501
1502
1503#ifdef CHECKMAXACTDELTA
1504/** checks that the stored maximal activity delta (if not invalid) is correct */
1505static
1507 SCIP* scip, /**< SCIP data structure */
1508 SCIP_CONSDATA* consdata /**< linear constraint data */
1509 )
1510{
1511 if( consdata->maxactdelta != SCIP_INVALID )
1512 {
1513 SCIP_Real maxactdelta = 0.0;
1514 SCIP_Real domain;
1515 SCIP_Real delta;
1516 SCIP_Real lb;
1517 SCIP_Real ub;
1518 int v;
1519
1520 for( v = consdata->nvars - 1; v >= 0; --v )
1521 {
1522 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1523 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1524
1525 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1526 {
1527 maxactdelta = SCIPinfinity(scip);
1528 break;
1529 }
1530
1531 domain = ub - lb;
1532 delta = REALABS(consdata->vals[v]) * domain;
1533
1534 if( delta > maxactdelta )
1535 {
1536 maxactdelta = delta;
1537 }
1538 }
1539 assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1540 }
1541}
1542#else
1543#define checkMaxActivityDelta(scip, consdata) /**/
1544#endif
1545
1546/** recompute maximal activity contribution for a single variable */
1547static
1549 SCIP* scip, /**< SCIP data structure */
1550 SCIP_CONSDATA* consdata /**< linear constraint data */
1551 )
1552{
1553 SCIP_Real delta;
1554 int v;
1555
1556 consdata->maxactdelta = 0.0;
1557
1558 if( !consdata->hasnonbinvalid )
1559 consdataCheckNonbinvar(consdata);
1560
1561 /* easy case, the problem consists only of binary variables */
1562 if( !consdata->hasnonbinvar )
1563 {
1564 for( v = consdata->nvars - 1; v >= 0; --v )
1565 {
1566 if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1567 {
1568 delta = REALABS(consdata->vals[v]);
1569
1570 if( delta > consdata->maxactdelta )
1571 {
1572 consdata->maxactdelta = delta;
1573 consdata->maxactdeltavar = consdata->vars[v];
1574 }
1575 }
1576 }
1577 return;
1578 }
1579
1580 for( v = consdata->nvars - 1; v >= 0; --v )
1581 {
1582 SCIP_Real domain;
1583 SCIP_Real lb;
1584 SCIP_Real ub;
1585
1586 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1587 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1588
1589 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1590 {
1591 consdata->maxactdelta = SCIPinfinity(scip);
1592 consdata->maxactdeltavar = consdata->vars[v];
1593 break;
1594 }
1595
1596 domain = ub - lb;
1597 delta = REALABS(consdata->vals[v]) * domain;
1598
1599 if( delta > consdata->maxactdelta )
1600 {
1601 consdata->maxactdelta = delta;
1602 consdata->maxactdeltavar = consdata->vars[v];
1603 }
1604 }
1605}
1606
1607
1608/** updates activities for a change in a bound */
1609static
1611 SCIP* scip, /**< SCIP data structure */
1612 SCIP_CONSDATA* consdata, /**< linear constraint data */
1613 SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1614 SCIP_Real oldbound, /**< old bound of variable */
1615 SCIP_Real newbound, /**< new bound of variable */
1616 SCIP_Real val, /**< coefficient of constraint entry */
1617 SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1618 SCIP_Bool global, /**< is it a global or a local bound change? */
1619 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1620 )
1621{
1622 QUAD_MEMBER(SCIP_Real* activity);
1623 QUAD_MEMBER(SCIP_Real delta);
1624 SCIP_Real* lastactivity;
1625 int* activityposinf;
1626 int* activityneginf;
1627 int* activityposhuge;
1628 int* activityneghuge;
1629 SCIP_Real oldcontribution;
1630 SCIP_Real newcontribution;
1631 SCIP_Bool validact;
1632 SCIP_Bool finitenewbound;
1633 SCIP_Bool hugevalnewcont;
1634
1635 assert(scip != NULL);
1636 assert(consdata != NULL);
1637 assert(global || (var != NULL));
1638 assert(consdata->validactivities);
1639 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
1640 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
1641 assert(consdata->lastminactivity < SCIP_INVALID);
1642 assert(consdata->lastmaxactivity < SCIP_INVALID);
1643 assert(consdata->minactivityneginf >= 0);
1644 assert(consdata->minactivityposinf >= 0);
1645 assert(consdata->maxactivityneginf >= 0);
1646 assert(consdata->maxactivityposinf >= 0);
1647 assert(consdata->minactivityneghuge >= 0);
1648 assert(consdata->minactivityposhuge >= 0);
1649 assert(consdata->maxactivityneghuge >= 0);
1650 assert(consdata->maxactivityposhuge >= 0);
1651 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
1652 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
1653 assert(consdata->lastglbminactivity < SCIP_INVALID);
1654 assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1655 assert(consdata->glbminactivityneginf >= 0);
1656 assert(consdata->glbminactivityposinf >= 0);
1657 assert(consdata->glbmaxactivityneginf >= 0);
1658 assert(consdata->glbmaxactivityposinf >= 0);
1659 assert(consdata->glbminactivityneghuge >= 0);
1660 assert(consdata->glbminactivityposhuge >= 0);
1661 assert(consdata->glbmaxactivityneghuge >= 0);
1662 assert(consdata->glbmaxactivityposhuge >= 0);
1663
1664 QUAD_ASSIGN(delta, 0.0);
1665
1666 /* we are updating global activities */
1667 if( global )
1668 {
1669 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1670 * lower bound + pos. coef: update minactivity
1671 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1672 * upper bound + pos. coef: update maxactivity
1673 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1674 */
1675 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1676 {
1677 if( val > 0.0 )
1678 {
1679 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1680 lastactivity = &(consdata->lastglbminactivity);
1681 activityposinf = &(consdata->glbminactivityposinf);
1682 activityneginf = &(consdata->glbminactivityneginf);
1683 activityposhuge = &(consdata->glbminactivityposhuge);
1684 activityneghuge = &(consdata->glbminactivityneghuge);
1685 validact = consdata->validglbminact;
1686 }
1687 else
1688 {
1689 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1690 lastactivity = &(consdata->lastglbmaxactivity);
1691 activityposinf = &(consdata->glbmaxactivityneginf);
1692 activityneginf = &(consdata->glbmaxactivityposinf);
1693 activityposhuge = &(consdata->glbmaxactivityposhuge);
1694 activityneghuge = &(consdata->glbmaxactivityneghuge);
1695 validact = consdata->validglbmaxact;
1696 }
1697 }
1698 else
1699 {
1700 if( val > 0.0 )
1701 {
1702 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1703 lastactivity = &(consdata->lastglbmaxactivity);
1704 activityposinf = &(consdata->glbmaxactivityposinf);
1705 activityneginf = &(consdata->glbmaxactivityneginf);
1706 activityposhuge = &(consdata->glbmaxactivityposhuge);
1707 activityneghuge = &(consdata->glbmaxactivityneghuge);
1708 validact = consdata->validglbmaxact;
1709 }
1710 else
1711 {
1712 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1713 lastactivity = &(consdata->lastglbminactivity);
1714 activityposinf = &(consdata->glbminactivityneginf);
1715 activityneginf = &(consdata->glbminactivityposinf);
1716 activityposhuge = &(consdata->glbminactivityposhuge);
1717 activityneghuge = &(consdata->glbminactivityneghuge);
1718 validact = consdata->validglbminact;
1719 }
1720 }
1721 }
1722 /* we are updating local activities */
1723 else
1724 {
1725 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1726 * lower bound + pos. coef: update minactivity
1727 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1728 * upper bound + pos. coef: update maxactivity
1729 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1730 */
1731 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1732 {
1733 if( val > 0.0 )
1734 {
1735 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1736 lastactivity = &(consdata->lastminactivity);
1737 activityposinf = &(consdata->minactivityposinf);
1738 activityneginf = &(consdata->minactivityneginf);
1739 activityposhuge = &(consdata->minactivityposhuge);
1740 activityneghuge = &(consdata->minactivityneghuge);
1741 validact = consdata->validminact;
1742 }
1743 else
1744 {
1745 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1746 lastactivity = &(consdata->lastmaxactivity);
1747 activityposinf = &(consdata->maxactivityneginf);
1748 activityneginf = &(consdata->maxactivityposinf);
1749 activityposhuge = &(consdata->maxactivityposhuge);
1750 activityneghuge = &(consdata->maxactivityneghuge);
1751 validact = consdata->validmaxact;
1752 }
1753 }
1754 else
1755 {
1756 if( val > 0.0 )
1757 {
1758 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1759 lastactivity = &(consdata->lastmaxactivity);
1760 activityposinf = &(consdata->maxactivityposinf);
1761 activityneginf = &(consdata->maxactivityneginf);
1762 activityposhuge = &(consdata->maxactivityposhuge);
1763 activityneghuge = &(consdata->maxactivityneghuge);
1764 validact = consdata->validmaxact;
1765 }
1766 else
1767 {
1768 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1769 lastactivity = &(consdata->lastminactivity);
1770 activityposinf = &(consdata->minactivityneginf);
1771 activityneginf = &(consdata->minactivityposinf);
1772 activityposhuge = &(consdata->minactivityposhuge);
1773 activityneghuge = &(consdata->minactivityneghuge);
1774 validact = consdata->validminact;
1775 }
1776 }
1777 }
1778
1779 oldcontribution = val * oldbound;
1780 newcontribution = val * newbound;
1781 hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1782 finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1783
1784 if( SCIPisInfinity(scip, REALABS(oldbound)) )
1785 {
1786 /* old bound was +infinity */
1787 if( oldbound > 0.0 )
1788 {
1789 assert((*activityposinf) >= 1);
1790
1791 /* we only have to do something if the new bound is not again +infinity */
1792 if( finitenewbound || newbound < 0.0 )
1793 {
1794 /* decrease the counter for positive infinite contributions */
1795 (*activityposinf)--;
1796
1797 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1798 if( !finitenewbound && newbound < 0.0 )
1799 (*activityneginf)++;
1800 else if( hugevalnewcont )
1801 {
1802 /* if the contribution of this variable is too large, increase the counter for huge values */
1803 if( newcontribution > 0.0 )
1804 (*activityposhuge)++;
1805 else
1806 (*activityneghuge)++;
1807 }
1808 /* "normal case": just add the contribution to the activity */
1809 else
1810 QUAD_ASSIGN(delta, newcontribution);
1811 }
1812 }
1813 /* old bound was -infinity */
1814 else
1815 {
1816 assert(oldbound < 0.0);
1817 assert((*activityneginf) >= 1);
1818
1819 /* we only have to do something ig the new bound is not again -infinity */
1820 if( finitenewbound || newbound > 0.0 )
1821 {
1822 /* decrease the counter for negative infinite contributions */
1823 (*activityneginf)--;
1824
1825 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1826 if( !finitenewbound && newbound > 0.0 )
1827 (*activityposinf)++;
1828 else if( hugevalnewcont )
1829 {
1830 /* if the contribution of this variable is too large, increase the counter for huge values */
1831 if( newcontribution > 0.0 )
1832 (*activityposhuge)++;
1833 else
1834 (*activityneghuge)++;
1835 }
1836 /* "normal case": just add the contribution to the activity */
1837 else
1838 QUAD_ASSIGN(delta, newcontribution);
1839 }
1840 }
1841 }
1842 else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1843 {
1844 /* old contribution was too large and positive */
1845 if( oldcontribution > 0.0 )
1846 {
1847 assert((*activityposhuge) >= 1);
1848
1849 /* decrease the counter for huge positive contributions; it might be increased again later,
1850 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1851 */
1852 (*activityposhuge)--;
1853
1854 if( !finitenewbound )
1855 {
1856 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1857 if( newbound > 0.0 )
1858 (*activityposinf)++;
1859 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1860 else
1861 (*activityneginf)++;
1862 }
1863 else if( hugevalnewcont )
1864 {
1865 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1866 if( newcontribution > 0.0 )
1867 (*activityposhuge)++;
1868 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1869 else
1870 (*activityneghuge)++;
1871 }
1872 /* "normal case": just add the contribution to the activity */
1873 else
1874 QUAD_ASSIGN(delta, newcontribution);
1875 }
1876 /* old contribution was too large and negative */
1877 else
1878 {
1879 assert(oldcontribution < 0.0);
1880 assert((*activityneghuge) >= 1);
1881
1882 /* decrease the counter for huge negative contributions; it might be increased again later,
1883 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1884 */
1885 (*activityneghuge)--;
1886
1887 if( !finitenewbound )
1888 {
1889 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1890 if( newbound > 0.0 )
1891 (*activityposinf)++;
1892 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1893 else
1894 (*activityneginf)++;
1895 }
1896 else if( hugevalnewcont )
1897 {
1898 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1899 if( newcontribution > 0.0 )
1900 (*activityposhuge)++;
1901 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1902 else
1903 (*activityneghuge)++;
1904 }
1905 /* "normal case": just add the contribution to the activity */
1906 else
1907 QUAD_ASSIGN(delta, newcontribution);
1908 }
1909 }
1910 /* old bound was finite and not too large */
1911 else
1912 {
1913 if( !finitenewbound )
1914 {
1915 /* if the new bound is +infinity, the old contribution has to be subtracted
1916 * and the counter for positive infinite contributions has to be increased
1917 */
1918 if( newbound > 0.0 )
1919 {
1920 (*activityposinf)++;
1921 QUAD_ASSIGN(delta, -oldcontribution);
1922 }
1923 /* if the new bound is -infinity, the old contribution has to be subtracted
1924 * and the counter for negative infinite contributions has to be increased
1925 */
1926 else
1927 {
1928 assert(newbound < 0.0 );
1929
1930 (*activityneginf)++;
1931 QUAD_ASSIGN(delta, -oldcontribution);
1932 }
1933 }
1934 /* if the contribution of this variable is too large, increase the counter for huge values */
1935 else if( hugevalnewcont )
1936 {
1937 if( newcontribution > 0.0 )
1938 {
1939 (*activityposhuge)++;
1940 QUAD_ASSIGN(delta, -oldcontribution);
1941 }
1942 else
1943 {
1944 (*activityneghuge)++;
1945 QUAD_ASSIGN(delta, -oldcontribution);
1946 }
1947 }
1948 /* "normal case": just update the activity */
1949 else
1950 {
1951 QUAD_ASSIGN(delta, newcontribution);
1952 SCIPquadprecSumQD(delta, delta, -oldcontribution);
1953 }
1954 }
1955
1956 /* update the activity, if the current value is valid and there was a change in the finite part */
1957 if( validact && (QUAD_TO_DBL(delta) != 0.0) )
1958 {
1959 SCIP_Real curractivity;
1960
1961 /* if the absolute value of the activity is increased, this is regarded as reliable,
1962 * otherwise, we check whether we can still trust the updated value
1963 */
1964 SCIPquadprecSumQD(*activity, *activity, QUAD_TO_DBL(delta));
1965
1966 curractivity = QUAD_TO_DBL(*activity);
1967 assert(!SCIPisInfinity(scip, -curractivity) && !SCIPisInfinity(scip, curractivity));
1968
1969 if( REALABS((*lastactivity)) < REALABS(curractivity) )
1970 {
1971 (*lastactivity) = curractivity;
1972 }
1973 else
1974 {
1975 if( checkreliability && SCIPisUpdateUnreliable(scip, curractivity, (*lastactivity)) )
1976 {
1977 SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1978 (global ? "global " : ""), curractivity);
1979
1980 /* mark the activity that was just changed and is not reliable anymore to be invalid */
1981 if( global )
1982 {
1983 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1984 consdata->validglbminact = FALSE;
1985 else
1986 consdata->validglbmaxact = FALSE;
1987 }
1988 else
1989 {
1990 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1991 consdata->validminact = FALSE;
1992 else
1993 consdata->validmaxact = FALSE;
1994 }
1995 }
1996 }
1997 }
1998}
1999
2000/** updates minimum and maximum activity for a change in lower bound */
2001static
2003 SCIP* scip, /**< SCIP data structure */
2004 SCIP_CONSDATA* consdata, /**< linear constraint data */
2005 SCIP_VAR* var, /**< variable that has been changed */
2006 SCIP_Real oldlb, /**< old lower bound of variable */
2007 SCIP_Real newlb, /**< new lower bound of variable */
2008 SCIP_Real val, /**< coefficient of constraint entry */
2009 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2010 )
2011{
2012 assert(scip != NULL);
2013 assert(consdata != NULL);
2014 assert(var != NULL);
2015
2016 if( consdata->validactivities )
2017 {
2018 consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
2019
2020 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2021 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2022 }
2023}
2024
2025/** updates minimum and maximum activity for a change in upper bound */
2026static
2028 SCIP* scip, /**< SCIP data structure */
2029 SCIP_CONSDATA* consdata, /**< linear constraint data */
2030 SCIP_VAR* var, /**< variable that has been changed */
2031 SCIP_Real oldub, /**< old upper bound of variable */
2032 SCIP_Real newub, /**< new upper bound of variable */
2033 SCIP_Real val, /**< coefficient of constraint entry */
2034 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2035 )
2036{
2037 assert(scip != NULL);
2038 assert(consdata != NULL);
2039 assert(var != NULL);
2040
2041 if( consdata->validactivities )
2042 {
2043 consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
2044
2045 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2046 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2047 }
2048}
2049
2050/** updates minimum and maximum global activity for a change in the global lower bound */
2051static
2053 SCIP* scip, /**< SCIP data structure */
2054 SCIP_CONSDATA* consdata, /**< linear constraint data */
2055 SCIP_Real oldlb, /**< old lower bound of variable */
2056 SCIP_Real newlb, /**< new lower bound of variable */
2057 SCIP_Real val, /**< coefficient of constraint entry */
2058 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2059 )
2060{
2061 assert(scip != NULL);
2062 assert(consdata != NULL);
2063
2064 if( consdata->validactivities )
2065 {
2066 consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2067
2068 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2069 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2070 }
2071}
2072
2073/** updates minimum and maximum global activity for a change in global upper bound */
2074static
2076 SCIP* scip, /**< SCIP data structure */
2077 SCIP_CONSDATA* consdata, /**< linear constraint data */
2078 SCIP_Real oldub, /**< old upper bound of variable */
2079 SCIP_Real newub, /**< new upper bound of variable */
2080 SCIP_Real val, /**< coefficient of constraint entry */
2081 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2082 )
2083{
2084 assert(scip != NULL);
2085 assert(consdata != NULL);
2086
2087 if( consdata->validactivities )
2088 {
2089 consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2090
2091 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2092 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2093 }
2094}
2095
2096/** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2097static
2099 SCIP* scip, /**< SCIP data structure */
2100 SCIP_CONSDATA* consdata, /**< linear constraint data */
2101 SCIP_VAR* var, /**< variable of constraint entry */
2102 SCIP_Real val, /**< coefficient of constraint entry */
2103 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2104 )
2105{
2106 assert(scip != NULL);
2107 assert(consdata != NULL);
2108 assert(var != NULL);
2109 assert(!SCIPisZero(scip, val));
2110
2111 /* update maximum absolute value */
2112 if( consdata->validmaxabsval )
2113 {
2114 SCIP_Real absval;
2115
2116 assert(consdata->maxabsval < SCIP_INVALID);
2117
2118 absval = REALABS(val);
2119 consdata->maxabsval = MAX(consdata->maxabsval, absval);
2120 }
2121
2122 /* update minimum absolute value */
2123 if( consdata->validminabsval )
2124 {
2125 SCIP_Real absval;
2126
2127 assert(consdata->minabsval < SCIP_INVALID);
2128
2129 absval = REALABS(val);
2130 consdata->minabsval = MIN(consdata->minabsval, absval);
2131 }
2132
2133 /* update minimum and maximum activity */
2134 if( consdata->validactivities )
2135 {
2136 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2137 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2138 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2139 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2140
2141 consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2142 consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2143 consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2144 consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2145 }
2146
2147 /* update maximum activity delta */
2148 if( consdata->maxactdeltavar == NULL || !SCIPisInfinity(scip, consdata->maxactdelta) )
2149 {
2150 SCIP_Real lb = SCIPvarGetLbLocal(var);
2151 SCIP_Real ub = SCIPvarGetUbLocal(var);
2152
2153 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
2154 {
2155 consdata->maxactdelta = SCIPinfinity(scip);
2156 consdata->maxactdeltavar = var;
2157 }
2158 else if( consdata->maxactdeltavar != NULL )
2159 {
2160 SCIP_Real domain = ub - lb;
2161 SCIP_Real delta = REALABS(val) * domain;
2162
2163 if( delta > consdata->maxactdelta )
2164 {
2165 consdata->maxactdelta = delta;
2166 consdata->maxactdeltavar = var;
2167 }
2168 }
2169 }
2170}
2171
2172/** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2173static
2175 SCIP* scip, /**< SCIP data structure */
2176 SCIP_CONSDATA* consdata, /**< linear constraint data */
2177 SCIP_VAR* var, /**< variable of constraint entry */
2178 SCIP_Real val, /**< coefficient of constraint entry */
2179 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2180 )
2181{
2182 assert(scip != NULL);
2183 assert(consdata != NULL);
2184 assert(var != NULL);
2185 assert(!SCIPisZero(scip, val));
2186
2187 /* invalidate maximum absolute value, if this coefficient was the maximum */
2188 if( consdata->validmaxabsval )
2189 {
2190 SCIP_Real absval;
2191
2192 absval = REALABS(val);
2193
2194 if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2195 {
2196 consdata->validmaxabsval = FALSE;
2197 consdata->maxabsval = SCIP_INVALID;
2198 }
2199 }
2200
2201 /* invalidate minimum absolute value, if this coefficient was the minimum */
2202 if( consdata->validminabsval )
2203 {
2204 SCIP_Real absval;
2205
2206 absval = REALABS(val);
2207
2208 if( SCIPisEQ(scip, absval, consdata->minabsval) )
2209 {
2210 consdata->validminabsval = FALSE;
2211 consdata->minabsval = SCIP_INVALID;
2212 }
2213 }
2214
2215 /* update minimum and maximum activity */
2216 if( consdata->validactivities )
2217 {
2218 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2219 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2220 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2221 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2222
2223 consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2224 consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2225 consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2226 consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2227 }
2228
2229 /* reset maximum activity delta so that it will be recalculated on the next real propagation */
2230 if( consdata->maxactdeltavar == var )
2231 {
2232 consdata->maxactdelta = SCIP_INVALID;
2233 consdata->maxactdeltavar = NULL;
2234 }
2235}
2236
2237/** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2238static
2240 SCIP* scip, /**< SCIP data structure */
2241 SCIP_CONSDATA* consdata, /**< linear constraint data */
2242 SCIP_VAR* var, /**< variable of constraint entry */
2243 SCIP_Real oldval, /**< old coefficient of constraint entry */
2244 SCIP_Real newval, /**< new coefficient of constraint entry */
2245 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2246 )
2247{
2248 /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2249 consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2250 consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2251}
2252
2253/** returns the maximum absolute value of all coefficients in the constraint */
2254static
2256 SCIP_CONSDATA* consdata /**< linear constraint data */
2257 )
2258{
2259 assert(consdata != NULL);
2260
2261 if( !consdata->validmaxabsval )
2262 consdataCalcMaxAbsval(consdata);
2263 assert(consdata->validmaxabsval);
2264 assert(consdata->maxabsval < SCIP_INVALID);
2265
2266 return consdata->maxabsval;
2267}
2268
2269/** returns the minimum absolute value of all coefficients in the constraint */
2270static
2272 SCIP_CONSDATA* consdata /**< linear constraint data */
2273 )
2274{
2275 assert(consdata != NULL);
2276
2277 if( !consdata->validminabsval )
2278 consdataCalcMinAbsval(consdata);
2279 assert(consdata->validminabsval);
2280 assert(consdata->minabsval < SCIP_INVALID);
2281
2282 return consdata->minabsval;
2283}
2284
2285/** calculates minimum and maximum local and global activity for constraint from scratch;
2286 * additionally recalculates maximum absolute value of coefficients
2287 */
2288static
2290 SCIP* scip, /**< SCIP data structure */
2291 SCIP_CONSDATA* consdata /**< linear constraint data */
2292 )
2293{
2294 int i;
2295
2296 assert(scip != NULL);
2297 assert(consdata != NULL);
2298 assert(!consdata->validactivities);
2299 assert(QUAD_TO_DBL(consdata->minactivity) >= SCIP_INVALID || consdata->validminact);
2300 assert(QUAD_TO_DBL(consdata->maxactivity) >= SCIP_INVALID || consdata->validmaxact);
2301 assert(QUAD_TO_DBL(consdata->glbminactivity) >= SCIP_INVALID || consdata->validglbminact);
2302 assert(QUAD_TO_DBL(consdata->glbmaxactivity) >= SCIP_INVALID || consdata->validglbmaxact);
2303
2304 consdata->validmaxabsval = TRUE;
2305 consdata->validminabsval = TRUE;
2306 consdata->validactivities = TRUE;
2307 consdata->validminact = TRUE;
2308 consdata->validmaxact = TRUE;
2309 consdata->validglbminact = TRUE;
2310 consdata->validglbmaxact = TRUE;
2311 consdata->maxabsval = 0.0;
2312 consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2313 QUAD_ASSIGN(consdata->minactivity, 0.0);
2314 QUAD_ASSIGN(consdata->maxactivity, 0.0);
2315 consdata->lastminactivity = 0.0;
2316 consdata->lastmaxactivity = 0.0;
2317 consdata->minactivityneginf = 0;
2318 consdata->minactivityposinf = 0;
2319 consdata->maxactivityneginf = 0;
2320 consdata->maxactivityposinf = 0;
2321 consdata->minactivityneghuge = 0;
2322 consdata->minactivityposhuge = 0;
2323 consdata->maxactivityneghuge = 0;
2324 consdata->maxactivityposhuge = 0;
2325 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
2326 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
2327 consdata->lastglbminactivity = 0.0;
2328 consdata->lastglbmaxactivity = 0.0;
2329 consdata->glbminactivityneginf = 0;
2330 consdata->glbminactivityposinf = 0;
2331 consdata->glbmaxactivityneginf = 0;
2332 consdata->glbmaxactivityposinf = 0;
2333 consdata->glbminactivityneghuge = 0;
2334 consdata->glbminactivityposhuge = 0;
2335 consdata->glbmaxactivityneghuge = 0;
2336 consdata->glbmaxactivityposhuge = 0;
2337
2338 for( i = 0; i < consdata->nvars; ++i )
2339 consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2340
2341 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
2342 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
2343 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
2344 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2345}
2346
2347/** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2348 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2349 */
2350static
2352 SCIP* scip, /**< SCIP data structure */
2353 SCIP_CONSDATA* consdata, /**< linear constraint */
2354 int posinf, /**< number of coefficients contributing pos. infinite value */
2355 int neginf, /**< number of coefficients contributing neg. infinite value */
2356 int poshuge, /**< number of coefficients contributing huge pos. value */
2357 int neghuge, /**< number of coefficients contributing huge neg. value */
2358 SCIP_Real delta, /**< value to subtract from stored minactivity
2359 * (contribution of the variable set to zero when getting residual activity) */
2360 SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2361 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2362 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2363 SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
2364 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2365 SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2366 )
2367{
2368 assert(scip != NULL);
2369 assert(consdata != NULL);
2370 assert(posinf >= 0);
2371 assert(neginf >= 0);
2372 assert(poshuge >= 0);
2373 assert(neghuge >= 0);
2374 assert(minactivity != NULL);
2375 assert(istight != NULL);
2376 assert(issettoinfinity != NULL);
2377
2378 /* if we have neg. infinite contributions, the minactivity is -infty */
2379 if( neginf > 0 )
2380 {
2381 *minactivity = -SCIPinfinity(scip);
2382 *issettoinfinity = TRUE;
2383 *istight = posinf == 0;
2384 }
2385 /* if we have pos. (and no neg.) infinite contributions, the minactivity is +infty */
2386 else if( posinf > 0 )
2387 {
2388 *minactivity = SCIPinfinity(scip);
2389 *issettoinfinity = TRUE;
2390 *istight = TRUE;
2391 }
2392 /* if we have neg. huge contributions or do not need a good relaxation, we just return -infty as minactivity */
2393 else if( neghuge > 0 || ( poshuge > 0 && !goodrelax ) )
2394 {
2395 *minactivity = -SCIPinfinity(scip);
2396 *issettoinfinity = TRUE;
2397 *istight = FALSE;
2398 }
2399 else
2400 {
2401 SCIP_Real QUAD(tmpactivity);
2402
2403 /* recompute minactivity if it is not valid */
2404 if( global )
2405 {
2406 if( !consdata->validglbminact )
2408 assert(consdata->validglbminact);
2409
2410 QUAD_ASSIGN_Q(tmpactivity, consdata->glbminactivity);
2411 }
2412 else
2413 {
2414 if( !consdata->validminact )
2416 assert(consdata->validminact);
2417
2418 QUAD_ASSIGN_Q(tmpactivity, consdata->minactivity);
2419 }
2420
2421 /* calculate residual minactivity */
2422 SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
2423
2424 /* we have no infinite and no neg. huge contributions, but pos. huge contributions; a feasible relaxation of the
2425 * minactivity is given by adding the number of positive huge contributions times the huge value
2426 */
2427 if( poshuge > 0 )
2428 {
2429 SCIPquadprecSumQD(tmpactivity, tmpactivity, poshuge * SCIPgetHugeValue(scip));
2430 *istight = FALSE;
2431 }
2432 /* all counters are zero, so the minactivity is tight */
2433 else
2434 *istight = TRUE;
2435
2436 /* round residual minactivity */
2437 *minactivity = QUAD_TO_DBL(tmpactivity);
2438 *issettoinfinity = FALSE;
2439 }
2440}
2441
2442/** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2443 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2444 */
2445static
2447 SCIP* scip, /**< SCIP data structure */
2448 SCIP_CONSDATA* consdata, /**< linear constraint */
2449 int posinf, /**< number of coefficients contributing pos. infinite value */
2450 int neginf, /**< number of coefficients contributing neg. infinite value */
2451 int poshuge, /**< number of coefficients contributing huge pos. value */
2452 int neghuge, /**< number of coefficients contributing huge neg. value */
2453 SCIP_Real delta, /**< value to subtract from stored maxactivity
2454 * (contribution of the variable set to zero when getting residual activity) */
2455 SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2456 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2457 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2458 SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
2459 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2460 SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2461 )
2462{
2463 assert(scip != NULL);
2464 assert(consdata != NULL);
2465 assert(posinf >= 0);
2466 assert(neginf >= 0);
2467 assert(poshuge >= 0);
2468 assert(neghuge >= 0);
2469 assert(maxactivity != NULL);
2470 assert(istight != NULL);
2471 assert(issettoinfinity != NULL);
2472
2473 /* if we have pos. infinite contributions, the maxactivity is +infty */
2474 if( posinf > 0 )
2475 {
2476 *maxactivity = SCIPinfinity(scip);
2477 *issettoinfinity = TRUE;
2478 *istight = neginf == 0;
2479 }
2480 /* if we have neg. (and no pos.) infinite contributions, the maxactivity is -infty */
2481 else if( neginf > 0 )
2482 {
2483 *maxactivity = -SCIPinfinity(scip);
2484 *issettoinfinity = TRUE;
2485 *istight = TRUE;
2486 }
2487 /* if we have pos. huge contributions or do not need a good relaxation, we just return +infty as maxactivity */
2488 else if( poshuge > 0 || ( neghuge > 0 && !goodrelax ) )
2489 {
2490 *maxactivity = SCIPinfinity(scip);
2491 *issettoinfinity = TRUE;
2492 *istight = FALSE;
2493 }
2494 else
2495 {
2496 SCIP_Real QUAD(tmpactivity);
2497
2498 /* recompute maxactivity if it is not valid */
2499 if( global )
2500 {
2501 if( !consdata->validglbmaxact )
2503 assert(consdata->validglbmaxact);
2504
2505 QUAD_ASSIGN_Q(tmpactivity, consdata->glbmaxactivity);
2506 }
2507 else
2508 {
2509 if( !consdata->validmaxact )
2511 assert(consdata->validmaxact);
2512
2513 QUAD_ASSIGN_Q(tmpactivity, consdata->maxactivity);
2514 }
2515
2516 /* calculate residual maxactivity */
2517 SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
2518
2519 /* we have no infinite and no pos. huge contributions, but neg. huge contributions; a feasible relaxation of the
2520 * maxactivity is given by subtracting the number of negative huge contributions times the huge value
2521 */
2522 if( neghuge > 0 )
2523 {
2524 SCIPquadprecSumQD(tmpactivity, tmpactivity, -neghuge * SCIPgetHugeValue(scip));
2525 *istight = FALSE;
2526 }
2527 /* all counters are zero, so the maxactivity is tight */
2528 else
2529 *istight = TRUE;
2530
2531 /* round residual maxactivity */
2532 *maxactivity = QUAD_TO_DBL(tmpactivity);
2533 *issettoinfinity = FALSE;
2534 }
2535}
2536
2537/** gets activity bounds for constraint */
2538static
2540 SCIP* scip, /**< SCIP data structure */
2541 SCIP_CONSDATA* consdata, /**< linear constraint */
2542 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2543 * relaxed activities ignored, anyway? */
2544 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2545 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2546 SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
2547 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2548 SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
2549 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2550 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2551 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2552
2553 )
2554{
2555 assert(scip != NULL);
2556 assert(consdata != NULL);
2557 assert(minactivity != NULL);
2558 assert(maxactivity != NULL);
2559 assert(isminsettoinfinity != NULL);
2560 assert(ismaxsettoinfinity != NULL);
2561
2562 if( !consdata->validactivities )
2563 {
2564 consdataCalcActivities(scip, consdata);
2565 assert(consdata->validminact);
2566 assert(consdata->validmaxact);
2567 }
2568 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2569 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2570 assert(consdata->minactivityneginf >= 0);
2571 assert(consdata->minactivityposinf >= 0);
2572 assert(consdata->maxactivityneginf >= 0);
2573 assert(consdata->maxactivityposinf >= 0);
2574
2575 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2576 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2577 minactivity, ismintight, isminsettoinfinity);
2578
2579 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2580 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2581 maxactivity, ismaxtight, ismaxsettoinfinity);
2582}
2583
2584/** calculates activity bounds for constraint after setting variable to zero */
2585static
2587 SCIP* scip, /**< SCIP data structure */
2588 SCIP_CONSDATA* consdata, /**< linear constraint */
2589 SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2590 SCIP_Real* resactivity, /**< pointer to store the residual activity */
2591 SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2592 SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2593 )
2594{
2595 SCIP_VAR* var;
2596 SCIP_Real val;
2597 SCIP_Real lb;
2598 SCIP_Real ub;
2599 int v;
2600
2601 assert(scip != NULL);
2602 assert(consdata != NULL);
2603 assert(cancelvar != NULL);
2604 assert(resactivity != NULL);
2605
2606 *resactivity = 0.0;
2607
2608 for( v = 0; v < consdata->nvars; ++v )
2609 {
2610 var = consdata->vars[v];
2611 assert(var != NULL);
2612 if( var == cancelvar )
2613 continue;
2614
2615 val = consdata->vals[v];
2616
2617 if( useglobalbounds )
2618 {
2619 lb = SCIPvarGetLbGlobal(var);
2620 ub = SCIPvarGetUbGlobal(var);
2621 }
2622 else
2623 {
2624 lb = SCIPvarGetLbLocal(var);
2625 ub = SCIPvarGetUbLocal(var);
2626 }
2627
2628 assert(!SCIPisZero(scip, val));
2629 assert(SCIPisLE(scip, lb, ub));
2630
2631 if( val > 0.0 )
2632 {
2633 if( isminresact )
2634 {
2635 assert(!SCIPisInfinity(scip, -lb));
2636 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2637 *resactivity += val*lb;
2638 }
2639 else
2640 {
2641 assert(!SCIPisInfinity(scip, ub));
2642 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2643 *resactivity += val*ub;
2644 }
2645 }
2646 else
2647 {
2648 if( isminresact)
2649 {
2650 assert(!SCIPisInfinity(scip, ub));
2651 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2652 *resactivity += val*ub;
2653 }
2654 else
2655 {
2656 assert(!SCIPisInfinity(scip, -lb));
2657 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2658 *resactivity += val*lb;
2659 }
2660 }
2661 }
2662 assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2663}
2664
2665/** gets activity bounds for constraint after setting variable to zero */
2666static
2668 SCIP* scip, /**< SCIP data structure */
2669 SCIP_CONSDATA* consdata, /**< linear constraint */
2670 SCIP_VAR* var, /**< variable to calculate activity residual for */
2671 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2672 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2673 * relaxed acticities ignored, anyway? */
2674 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2675 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2676 SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
2677 * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
2678 SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
2679 * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
2680 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2681 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2682 )
2683{
2684 SCIP_Real minactbound;
2685 SCIP_Real maxactbound;
2686 SCIP_Real absval;
2687
2688 assert(scip != NULL);
2689 assert(consdata != NULL);
2690 assert(var != NULL);
2691 assert(minresactivity != NULL);
2692 assert(maxresactivity != NULL);
2693 assert(ismintight != NULL);
2694 assert(ismaxtight != NULL);
2695 assert(isminsettoinfinity != NULL);
2696 assert(ismaxsettoinfinity != NULL);
2697
2698 /* get activity bounds of linear constraint */
2699 if( !consdata->validactivities )
2700 {
2701 consdataCalcActivities(scip, consdata);
2702 assert(consdata->validminact);
2703 assert(consdata->validmaxact);
2704 }
2705 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2706 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2707 assert(consdata->minactivityneginf >= 0);
2708 assert(consdata->minactivityposinf >= 0);
2709 assert(consdata->maxactivityneginf >= 0);
2710 assert(consdata->maxactivityposinf >= 0);
2711 assert(consdata->minactivityneghuge >= 0);
2712 assert(consdata->minactivityposhuge >= 0);
2713 assert(consdata->maxactivityneghuge >= 0);
2714 assert(consdata->maxactivityposhuge >= 0);
2715
2716 if( val > 0.0 )
2717 {
2718 minactbound = SCIPvarGetLbLocal(var);
2719 maxactbound = SCIPvarGetUbLocal(var);
2720 absval = val;
2721 }
2722 else
2723 {
2724 minactbound = -SCIPvarGetUbLocal(var);
2725 maxactbound = -SCIPvarGetLbLocal(var);
2726 absval = -val;
2727 }
2728
2729 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2730 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2731 */
2732 if( SCIPisInfinity(scip, minactbound) )
2733 {
2734 assert(consdata->minactivityposinf >= 1);
2735
2736 getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2737 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2738 minresactivity, ismintight, isminsettoinfinity);
2739 }
2740 else if( SCIPisInfinity(scip, -minactbound) )
2741 {
2742 assert(consdata->minactivityneginf >= 1);
2743
2744 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2745 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2746 minresactivity, ismintight, isminsettoinfinity);
2747 }
2748 else if( SCIPisHugeValue(scip, minactbound * absval) )
2749 {
2750 assert(consdata->minactivityposhuge >= 1);
2751
2752 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2753 consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2754 minresactivity, ismintight, isminsettoinfinity);
2755 }
2756 else if( SCIPisHugeValue(scip, -minactbound * absval) )
2757 {
2758 assert(consdata->minactivityneghuge >= 1);
2759
2760 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2761 consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2762 minresactivity, ismintight, isminsettoinfinity);
2763 }
2764 else
2765 {
2766 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2767 consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2768 minresactivity, ismintight, isminsettoinfinity);
2769 }
2770
2771 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2772 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2773 */
2774 if( SCIPisInfinity(scip, -maxactbound) )
2775 {
2776 assert(consdata->maxactivityneginf >= 1);
2777
2778 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2779 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2780 maxresactivity, ismaxtight, ismaxsettoinfinity);
2781 }
2782 else if( SCIPisInfinity(scip, maxactbound) )
2783 {
2784 assert(consdata->maxactivityposinf >= 1);
2785
2786 getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2787 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2788 maxresactivity, ismaxtight, ismaxsettoinfinity);
2789 }
2790 else if( SCIPisHugeValue(scip, absval * maxactbound) )
2791 {
2792 assert(consdata->maxactivityposhuge >= 1);
2793
2794 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2795 consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2796 maxresactivity, ismaxtight, ismaxsettoinfinity);
2797 }
2798 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2799 {
2800 assert(consdata->maxactivityneghuge >= 1);
2801
2802 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2803 consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2804 maxresactivity, ismaxtight, ismaxsettoinfinity);
2805 }
2806 else
2807 {
2808 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2809 consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2810 maxresactivity, ismaxtight, ismaxsettoinfinity);
2811 }
2812}
2813
2814/** gets global activity bounds for constraint */
2815static
2817 SCIP* scip, /**< SCIP data structure */
2818 SCIP_CONSDATA* consdata, /**< linear constraint */
2819 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2820 * relaxed acticities ignored, anyway? */
2821 SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2822 SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2823 SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
2824 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2825 SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
2826 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2827 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2828 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2829 )
2830{
2831 assert(scip != NULL);
2832 assert(consdata != NULL);
2833 assert((glbminactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL)
2834 || (glbmaxactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
2835
2836 if( !consdata->validactivities )
2837 {
2838 consdataCalcActivities(scip, consdata);
2839 assert(consdata->validglbminact);
2840 assert(consdata->validglbmaxact);
2841 }
2842 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2843 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2844 assert(consdata->glbminactivityneginf >= 0);
2845 assert(consdata->glbminactivityposinf >= 0);
2846 assert(consdata->glbmaxactivityneginf >= 0);
2847 assert(consdata->glbmaxactivityposinf >= 0);
2848 assert(consdata->glbminactivityneghuge >= 0);
2849 assert(consdata->glbminactivityposhuge >= 0);
2850 assert(consdata->glbmaxactivityneghuge >= 0);
2851 assert(consdata->glbmaxactivityposhuge >= 0);
2852
2853 if( glbminactivity != NULL )
2854 {
2855 assert(isminsettoinfinity != NULL);
2856 assert(ismintight != NULL);
2857
2858 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2859 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2860 glbminactivity, ismintight, isminsettoinfinity);
2861 }
2862
2863 if( glbmaxactivity != NULL )
2864 {
2865 assert(ismaxsettoinfinity != NULL);
2866 assert(ismaxtight != NULL);
2867
2868 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2869 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2870 glbmaxactivity, ismaxtight, ismaxsettoinfinity);
2871 }
2872}
2873
2874/** gets global activity bounds for constraint after setting variable to zero */
2875static
2877 SCIP* scip, /**< SCIP data structure */
2878 SCIP_CONSDATA* consdata, /**< linear constraint */
2879 SCIP_VAR* var, /**< variable to calculate activity residual for */
2880 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2881 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2882 * relaxed acticities ignored, anyway? */
2883 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2884 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2885 SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
2886 * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
2887 SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
2888 * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
2889 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2890 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2891 )
2892{
2893 SCIP_Real minactbound;
2894 SCIP_Real maxactbound;
2895 SCIP_Real absval;
2896
2897 assert(scip != NULL);
2898 assert(consdata != NULL);
2899 assert(var != NULL);
2900 assert((minresactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL )
2901 || (maxresactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
2902
2903 /* get activity bounds of linear constraint */
2904 if( !consdata->validactivities )
2905 consdataCalcActivities(scip, consdata);
2906
2907 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2908 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2909 assert(consdata->glbminactivityneginf >= 0);
2910 assert(consdata->glbminactivityposinf >= 0);
2911 assert(consdata->glbmaxactivityneginf >= 0);
2912 assert(consdata->glbmaxactivityposinf >= 0);
2913
2914 if( val > 0.0 )
2915 {
2916 minactbound = SCIPvarGetLbGlobal(var);
2917 maxactbound = SCIPvarGetUbGlobal(var);
2918 absval = val;
2919 }
2920 else
2921 {
2922 minactbound = -SCIPvarGetUbGlobal(var);
2923 maxactbound = -SCIPvarGetLbGlobal(var);
2924 absval = -val;
2925 }
2926
2927 if( minresactivity != NULL )
2928 {
2929 assert(isminsettoinfinity != NULL);
2930 assert(ismintight != NULL);
2931
2932 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2933 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2934 */
2935 if( SCIPisInfinity(scip, minactbound) )
2936 {
2937 assert(consdata->glbminactivityposinf >= 1);
2938
2939 getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2940 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2941 minresactivity, ismintight, isminsettoinfinity);
2942 }
2943 else if( SCIPisInfinity(scip, -minactbound) )
2944 {
2945 assert(consdata->glbminactivityneginf >= 1);
2946
2947 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2948 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2949 minresactivity, ismintight, isminsettoinfinity);
2950 }
2951 else if( SCIPisHugeValue(scip, minactbound * absval) )
2952 {
2953 assert(consdata->glbminactivityposhuge >= 1);
2954
2955 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2956 consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2957 minresactivity, ismintight, isminsettoinfinity);
2958 }
2959 else if( SCIPisHugeValue(scip, -minactbound * absval) )
2960 {
2961 assert(consdata->glbminactivityneghuge >= 1);
2962
2963 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2964 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
2965 minresactivity, ismintight, isminsettoinfinity);
2966 }
2967 else
2968 {
2969 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2970 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
2971 goodrelax, minresactivity, ismintight, isminsettoinfinity);
2972 }
2973 }
2974
2975 if( maxresactivity != NULL )
2976 {
2977 assert(ismaxsettoinfinity != NULL);
2978 assert(ismaxtight != NULL);
2979
2980 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2981 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2982 */
2983 if( SCIPisInfinity(scip, -maxactbound) )
2984 {
2985 assert(consdata->glbmaxactivityneginf >= 1);
2986
2987 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
2988 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2989 maxresactivity, ismaxtight, ismaxsettoinfinity);
2990 }
2991 else if( SCIPisInfinity(scip, maxactbound) )
2992 {
2993 assert(consdata->glbmaxactivityposinf >= 1);
2994
2995 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
2996 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2997 maxresactivity, ismaxtight, ismaxsettoinfinity);
2998 }
2999 else if( SCIPisHugeValue(scip, absval * maxactbound) )
3000 {
3001 assert(consdata->glbmaxactivityposhuge >= 1);
3002
3003 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3004 consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3005 maxresactivity, ismaxtight, ismaxsettoinfinity);
3006 }
3007 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3008 {
3009 assert(consdata->glbmaxactivityneghuge >= 1);
3010
3011 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3012 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3013 maxresactivity, ismaxtight, ismaxsettoinfinity);
3014 }
3015 else
3016 {
3017 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3018 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3019 goodrelax, maxresactivity, ismaxtight, ismaxsettoinfinity);
3020 }
3021 }
3022}
3023
3024/** calculates the activity of the linear constraint for given solution */
3025static
3027 SCIP* scip, /**< SCIP data structure */
3028 SCIP_CONSDATA* consdata, /**< linear constraint data */
3029 SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3030 )
3031{
3032 SCIP_Real activity;
3033
3034 assert(scip != NULL);
3035 assert(consdata != NULL);
3036
3037 if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3038 activity = consdataComputePseudoActivity(scip, consdata);
3039 else
3040 {
3041 SCIP_Real solval;
3042 int nposinf;
3043 int nneginf;
3044 SCIP_Bool negsign;
3045 int v;
3046
3047 activity = 0.0;
3048 nposinf = 0;
3049 nneginf = 0;
3050
3051 for( v = 0; v < consdata->nvars; ++v )
3052 {
3053 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3054
3055 if( consdata->vals[v] < 0 )
3056 negsign = TRUE;
3057 else
3058 negsign = FALSE;
3059
3060 if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3061 ++nposinf;
3062 else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3063 ++nneginf;
3064 else
3065 activity += consdata->vals[v] * solval;
3066 }
3067 assert(nneginf >= 0 && nposinf >= 0);
3068
3069 SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3070
3071 /* check for amount of infinity values and correct the activity */
3072 if( nposinf > 0 && nneginf > 0 )
3073 activity = (consdata->rhs + consdata->lhs) / 2;
3074 else if( nposinf > 0 )
3075 activity = SCIPinfinity(scip);
3076 else if( nneginf > 0 )
3077 activity = -SCIPinfinity(scip);
3078
3079 SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3080 }
3081
3082 if( activity == SCIP_INVALID ) /*lint !e777*/
3083 return activity;
3084 else if( activity < 0 )
3085 activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3086 else
3087 activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3088
3089 return activity;
3090}
3091
3092/** calculates the feasibility of the linear constraint for given solution */
3093static
3095 SCIP* scip, /**< SCIP data structure */
3096 SCIP_CONSDATA* consdata, /**< linear constraint data */
3097 SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3098 )
3099{
3100 SCIP_Real activity;
3101
3102 assert(scip != NULL);
3103 assert(consdata != NULL);
3104
3105 activity = consdataGetActivity(scip, consdata, sol);
3106
3107 if( activity == SCIP_INVALID ) /*lint !e777*/
3108 return -SCIPinfinity(scip);
3109
3110 return MIN(consdata->rhs - activity, activity - consdata->lhs);
3111}
3112
3113/** updates bit signatures after adding a single coefficient */
3114static
3116 SCIP_CONSDATA* consdata, /**< linear constraint data */
3117 int pos /**< position of coefficient to update signatures for */
3118 )
3119{
3120 uint64_t varsignature;
3121 SCIP_Real lb;
3122 SCIP_Real ub;
3123 SCIP_Real val;
3124
3125 assert(consdata != NULL);
3126 assert(consdata->validsignature);
3127
3128 varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3129 lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3130 ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3131 val = consdata->vals[pos];
3132 if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3133 consdata->possignature |= varsignature;
3134 if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3135 consdata->negsignature |= varsignature;
3136}
3137
3138/** calculates the bit signatures of the given constraint data */
3139static
3141 SCIP_CONSDATA* consdata /**< linear constraint data */
3142 )
3143{
3144 assert(consdata != NULL);
3145
3146 if( !consdata->validsignature )
3147 {
3148 int i;
3149
3150 consdata->validsignature = TRUE;
3151 consdata->possignature = 0;
3152 consdata->negsignature = 0;
3153 for( i = 0; i < consdata->nvars; ++i )
3154 consdataUpdateSignatures(consdata, i);
3155 }
3156}
3157
3158/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3159static
3161{ /*lint --e{715}*/
3162 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3163 SCIP_VAR* var1;
3164 SCIP_VAR* var2;
3165
3166 assert(consdata != NULL);
3167 assert(0 <= ind1 && ind1 < consdata->nvars);
3168 assert(0 <= ind2 && ind2 < consdata->nvars);
3169
3170 var1 = consdata->vars[ind1];
3171 var2 = consdata->vars[ind2];
3172
3173 /* exactly one variable is binary */
3174 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3175 {
3176 return (SCIPvarIsBinary(var1) ? -1 : +1);
3177 }
3178 /* both variables are binary */
3179 else if( SCIPvarIsBinary(var1) )
3180 {
3181 return SCIPvarCompare(var1, var2);
3182 }
3183 else
3184 {
3185 SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3186 SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3187
3188 if( vartype1 < vartype2 )
3189 return -1;
3190 else if( vartype1 > vartype2 )
3191 return +1;
3192 else
3193 return SCIPvarCompare(var1, var2);
3194 }
3195}
3196
3197/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3198static
3199SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
3200{ /*lint --e{715}*/
3201 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3202 SCIP_VAR* var1;
3203 SCIP_VAR* var2;
3204
3205 assert(consdata != NULL);
3206 assert(0 <= ind1 && ind1 < consdata->nvars);
3207 assert(0 <= ind2 && ind2 < consdata->nvars);
3208
3209 var1 = consdata->vars[ind1];
3210 var2 = consdata->vars[ind2];
3211
3212 /* exactly one variable is binary */
3213 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3214 {
3215 return (SCIPvarIsBinary(var1) ? -1 : +1);
3216 }
3217 /* both variables are binary */
3218 else if( SCIPvarIsBinary(var1) )
3219 {
3220 SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3221 SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3222
3223 if( EPSGT(abscoef1, abscoef2, 1e-9) )
3224 return -1;
3225 else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3226 return +1;
3227 else
3228 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3229 }
3230 else
3231 {
3232 SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3233 SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3234
3235 if( vartype1 < vartype2 )
3236 {
3237 return -1;
3238 }
3239 else if( vartype1 > vartype2 )
3240 {
3241 return +1;
3242 }
3243 else
3244 {
3245 /* both variables are continuous */
3246 if( !SCIPvarIsIntegral(var1) )
3247 {
3248 assert(!SCIPvarIsIntegral(var2));
3249 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3250 }
3251 else
3252 {
3253 SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3254 SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3255
3256 if( EPSGT(abscont1, abscont2, 1e-9) )
3257 return -1;
3258 else if( EPSGT(abscont2, abscont1, 1e-9) )
3259 return +1;
3260 else
3261 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3262 }
3263 }
3264 }
3265}
3266
3267/** permutes the constraint's variables according to a given permutation. */
3268static
3270 SCIP_CONSDATA* consdata, /**< the constraint data */
3271 int* perm, /**< the target permutation */
3272 int nvars /**< the number of variables */
3273 )
3274{ /*lint --e{715}*/
3275 SCIP_VAR* varv;
3276 SCIP_EVENTDATA* eventdatav;
3277 SCIP_Real valv;
3278 int v;
3279 int i;
3280 int nexti;
3281
3282 assert(perm != NULL);
3283 assert(consdata != NULL);
3284
3285 /* permute the variables in the linear constraint according to the target permutation */
3286 eventdatav = NULL;
3287 for( v = 0; v < nvars; ++v )
3288 {
3289 if( perm[v] != v )
3290 {
3291 varv = consdata->vars[v];
3292 valv = consdata->vals[v];
3293 if( consdata->eventdata != NULL )
3294 eventdatav = consdata->eventdata[v];
3295 i = v;
3296 do
3297 {
3298 assert(0 <= perm[i] && perm[i] < nvars);
3299 assert(perm[i] != i);
3300 consdata->vars[i] = consdata->vars[perm[i]];
3301 consdata->vals[i] = consdata->vals[perm[i]];
3302 if( consdata->eventdata != NULL )
3303 {
3304 consdata->eventdata[i] = consdata->eventdata[perm[i]];
3305 consdata->eventdata[i]->varpos = i;
3306 }
3307 nexti = perm[i];
3308 perm[i] = i;
3309 i = nexti;
3310 }
3311 while( perm[i] != v );
3312 consdata->vars[i] = varv;
3313 consdata->vals[i] = valv;
3314 if( consdata->eventdata != NULL )
3315 {
3316 consdata->eventdata[i] = eventdatav;
3317 consdata->eventdata[i]->varpos = i;
3318 }
3319 perm[i] = i;
3320 }
3321 }
3322#ifdef SCIP_DEBUG
3323 /* check sorting */
3324 for( v = 0; v < nvars; ++v )
3325 {
3326 assert(perm[v] == v);
3327 assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3328 }
3329#endif
3330}
3331
3332/** sorts linear constraint's variables depending on the stage of the solving process:
3333 * - during PRESOLVING
3334 * sorts variables by binaries, integers, implicit integers, and continuous variables,
3335 * and the variables of the same type by non-decreasing variable index
3336 *
3337 * - during SOLVING
3338 * sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables,
3339 * and binary and integer variables by their global max activity delta (within each group),
3340 * ties within a group are broken by problem index of the variable.
3341 *
3342 * This fastens the propagation time of the constraint handler.
3343 */
3344static
3346 SCIP* scip, /**< SCIP data structure */
3347 SCIP_CONSDATA* consdata /**< linear constraint data */
3348 )
3349{
3350 assert(scip != NULL);
3351 assert(consdata != NULL);
3352
3353 /* check if there are variables for sorting */
3354 if( consdata->nvars <= 1 )
3355 {
3356 consdata->indexsorted = TRUE;
3357 consdata->coefsorted = TRUE;
3358 consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3359 }
3360 else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3361 || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3362 {
3363 int* perm;
3364 int v;
3365
3366 /* get temporary memory to store the sorted permutation */
3367 SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3368
3369 /* call sorting method */
3371 SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3372 else
3373 SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3374
3375 permSortConsdata(consdata, perm, consdata->nvars);
3376
3377 /* free temporary memory */
3378 SCIPfreeBufferArray(scip, &perm);
3379
3381 {
3382 consdata->indexsorted = FALSE;
3383 consdata->coefsorted = TRUE;
3384
3385 /* count binary variables in the sorted vars array */
3386 consdata->nbinvars = 0;
3387 for( v = 0; v < consdata->nvars; ++v )
3388 {
3389 if( SCIPvarIsBinary(consdata->vars[v]) )
3390 ++consdata->nbinvars;
3391 else
3392 break;
3393 }
3394 }
3395 else
3396 {
3397 consdata->indexsorted = TRUE;
3398 consdata->coefsorted = FALSE;
3399 }
3400 }
3401
3402 return SCIP_OKAY;
3403}
3404
3405
3406/*
3407 * local linear constraint handler methods
3408 */
3409
3410/** sets left hand side of linear constraint */
3411static
3413 SCIP* scip, /**< SCIP data structure */
3414 SCIP_CONS* cons, /**< linear constraint */
3415 SCIP_Real lhs /**< new left hand side */
3416 )
3417{
3418 SCIP_CONSDATA* consdata;
3419 SCIP_Bool locked;
3420 int i;
3421
3422 assert(scip != NULL);
3423 assert(cons != NULL);
3424
3425 /* adjust value to be not beyond infinity */
3426 if( SCIPisInfinity(scip, -lhs) )
3427 lhs = -SCIPinfinity(scip);
3428 else if( SCIPisInfinity(scip, lhs) )
3429 lhs = SCIPinfinity(scip);
3430
3431 consdata = SCIPconsGetData(cons);
3432 assert(consdata != NULL);
3433 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3434
3435 /* check whether the side is not changed */
3436 if( SCIPisEQ(scip, consdata->lhs, lhs) )
3437 return SCIP_OKAY;
3438
3439 assert(!SCIPisInfinity(scip, ABS(consdata->lhs)) || !SCIPisInfinity(scip, ABS(lhs)));
3440
3441 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3442 if( SCIPisEQ(scip, lhs, consdata->rhs) )
3443 {
3444 consdata->rhs = lhs;
3445 assert(consdata->row == NULL);
3446 }
3447
3448 locked = FALSE;
3449 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3450 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3451
3452 /* if necessary, update the rounding locks of variables */
3453 if( locked )
3454 {
3455 if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3456 {
3457 SCIP_VAR** vars;
3458 SCIP_Real* vals;
3459 int v;
3460
3461 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3462 vars = consdata->vars;
3463 vals = consdata->vals;
3464
3465 for( v = 0; v < consdata->nvars; ++v )
3466 {
3467 assert(vars[v] != NULL);
3468 assert(!SCIPisZero(scip, vals[v]));
3469
3470 if( SCIPisPositive(scip, vals[v]) )
3471 {
3472 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3473 }
3474 else
3475 {
3476 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3477 }
3478 }
3479 }
3480 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3481 {
3482 SCIP_VAR** vars;
3483 SCIP_Real* vals;
3484 int v;
3485
3486 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3487 vars = consdata->vars;
3488 vals = consdata->vals;
3489
3490 for( v = 0; v < consdata->nvars; ++v )
3491 {
3492 assert(vars[v] != NULL);
3493 assert(!SCIPisZero(scip, vals[v]));
3494
3495 if( SCIPisPositive(scip, vals[v]) )
3496 {
3497 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3498 }
3499 else
3500 {
3501 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3502 }
3503 }
3504 }
3505 }
3506
3507 /* check whether the left hand side is increased, if and only if that's the case we maybe can propagate, tighten and add more cliques */
3508 if( !SCIPisInfinity(scip, ABS(lhs)) && SCIPisGT(scip, lhs, consdata->lhs) )
3509 {
3510 consdata->boundstightened = 0;
3511 consdata->presolved = FALSE;
3512 consdata->cliquesadded = FALSE;
3513 consdata->implsadded = FALSE;
3514
3515 /* mark the constraint for propagation */
3516 if( SCIPconsIsTransformed(cons) )
3517 {
3519 }
3520 }
3521
3522 /* set new left hand side and update constraint data */
3523 consdata->lhs = lhs;
3524 consdata->changed = TRUE;
3525 consdata->normalized = FALSE;
3526 consdata->upgradetried = FALSE;
3527 consdata->rangedrowpropagated = 0;
3528
3529 /* update the lhs of the LP row */
3530 if( consdata->row != NULL )
3531 {
3532 SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3533 }
3534
3535 return SCIP_OKAY;
3536}
3537
3538/** sets right hand side of linear constraint */
3539static
3541 SCIP* scip, /**< SCIP data structure */
3542 SCIP_CONS* cons, /**< linear constraint */
3543 SCIP_Real rhs /**< new right hand side */
3544 )
3545{
3546 SCIP_CONSDATA* consdata;
3547 SCIP_Bool locked;
3548 int i;
3549
3550 assert(scip != NULL);
3551 assert(cons != NULL);
3552
3553 /* adjust value to be not beyond infinity */
3554 if( SCIPisInfinity(scip, rhs) )
3555 rhs = SCIPinfinity(scip);
3556 else if( SCIPisInfinity(scip, -rhs) )
3557 rhs = -SCIPinfinity(scip);
3558
3559 consdata = SCIPconsGetData(cons);
3560 assert(consdata != NULL);
3561 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3562
3563 /* check whether the side is not changed */
3564 if( SCIPisEQ(scip, consdata->rhs, rhs) )
3565 return SCIP_OKAY;
3566
3567 assert(!SCIPisInfinity(scip, ABS(consdata->rhs)) || !SCIPisInfinity(scip, ABS(rhs)));
3568
3569 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3570 if( SCIPisEQ(scip, rhs, consdata->lhs) )
3571 {
3572 consdata->lhs = rhs;
3573 assert(consdata->row == NULL);
3574 }
3575
3576 locked = FALSE;
3577 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3578 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3579
3580 /* if necessary, update the rounding locks of variables */
3581 if( locked )
3582 {
3583 assert(SCIPconsIsTransformed(cons));
3584
3585 if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3586 {
3587 SCIP_VAR** vars;
3588 SCIP_Real* vals;
3589 int v;
3590
3591 /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3592 vars = consdata->vars;
3593 vals = consdata->vals;
3594
3595 for( v = 0; v < consdata->nvars; ++v )
3596 {
3597 assert(vars[v] != NULL);
3598 assert(!SCIPisZero(scip, vals[v]));
3599
3600 if( SCIPisPositive(scip, vals[v]) )
3601 {
3602 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3603 }
3604 else
3605 {
3606 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3607 }
3608 }
3609 }
3610 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3611 {
3612 SCIP_VAR** vars;
3613 SCIP_Real* vals;
3614 int v;
3615
3616 /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3617 vars = consdata->vars;
3618 vals = consdata->vals;
3619
3620 for( v = 0; v < consdata->nvars; ++v )
3621 {
3622 assert(vars[v] != NULL);
3623 assert(!SCIPisZero(scip, vals[v]));
3624
3625 if( SCIPisPositive(scip, vals[v]) )
3626 {
3627 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3628 }
3629 else
3630 {
3631 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3632 }
3633 }
3634 }
3635 }
3636
3637 /* check whether the right hand side is decreased, if and only if that's the case we maybe can propagate, tighten and add more cliques */
3638 if( !SCIPisInfinity(scip, ABS(rhs)) && SCIPisLT(scip, rhs, consdata->rhs) )
3639 {
3640 consdata->boundstightened = 0;
3641 consdata->presolved = FALSE;
3642 consdata->cliquesadded = FALSE;
3643 consdata->implsadded = FALSE;
3644
3645 /* mark the constraint for propagation */
3646 if( SCIPconsIsTransformed(cons) )
3647 {
3649 }
3650 }
3651
3652 /* set new right hand side and update constraint data */
3653 consdata->rhs = rhs;
3654 consdata->changed = TRUE;
3655 consdata->normalized = FALSE;
3656 consdata->upgradetried = FALSE;
3657 consdata->rangedrowpropagated = 0;
3658
3659 /* update the rhs of the LP row */
3660 if( consdata->row != NULL )
3661 {
3662 SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3663 }
3664
3665 return SCIP_OKAY;
3666}
3667
3668/** adds coefficient in linear constraint */
3669static
3671 SCIP* scip, /**< SCIP data structure */
3672 SCIP_CONS* cons, /**< linear constraint */
3673 SCIP_VAR* var, /**< variable of constraint entry */
3674 SCIP_Real val /**< coefficient of constraint entry */
3675 )
3676{
3677 SCIP_CONSDATA* consdata;
3678 SCIP_Bool transformed;
3679
3680 assert(scip != NULL);
3681 assert(cons != NULL);
3682 assert(var != NULL);
3683
3684 /* relaxation-only variables must not be used in checked or enforced constraints */
3685 assert(!SCIPvarIsRelaxationOnly(var) || (!SCIPconsIsChecked(cons) && !SCIPconsIsEnforced(cons)));
3686 consdata = SCIPconsGetData(cons);
3687 assert(consdata != NULL);
3688
3689 /* are we in the transformed problem? */
3690 transformed = SCIPconsIsTransformed(cons);
3691
3692 /* always use transformed variables in transformed constraints */
3693 if( transformed )
3694 {
3695 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3696 }
3697 assert(var != NULL);
3698 assert(transformed == SCIPvarIsTransformed(var));
3699
3700 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3701 consdata->vars[consdata->nvars] = var;
3702 consdata->vals[consdata->nvars] = val;
3703 consdata->nvars++;
3704
3705 /* capture variable */
3706 SCIP_CALL( SCIPcaptureVar(scip, var) );
3707
3708 /* if we are in transformed problem, the variable needs an additional event data */
3709 if( transformed )
3710 {
3711 if( consdata->eventdata != NULL )
3712 {
3713 SCIP_CONSHDLR* conshdlr;
3714 SCIP_CONSHDLRDATA* conshdlrdata;
3715
3716 /* check for event handler */
3717 conshdlr = SCIPconsGetHdlr(cons);
3718 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3719 assert(conshdlrdata != NULL);
3720 assert(conshdlrdata->eventhdlr != NULL);
3721
3722 /* initialize eventdata array */
3723 consdata->eventdata[consdata->nvars-1] = NULL;
3724
3725 /* catch bound change events of variable */
3726 SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3727 }
3728
3729 /* update minimum and maximum activities */
3730 if( !SCIPisZero(scip, val) )
3731 consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3732 }
3733
3734 /* install rounding locks for new variable with non-zero coefficient */
3735 if( !SCIPisZero(scip, val) )
3736 {
3737 SCIP_CALL( lockRounding(scip, cons, var, val) );
3738 }
3739
3740 /* mark the constraint for propagation */
3741 if( transformed )
3742 {
3744 }
3745
3746 consdata->boundstightened = 0;
3747 consdata->presolved = FALSE;
3748 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3749
3750 if( consdata->validsignature )
3751 consdataUpdateSignatures(consdata, consdata->nvars-1);
3752
3753 consdata->changed = TRUE;
3754 consdata->normalized = FALSE;
3755 consdata->upgradetried = FALSE;
3756 consdata->cliquesadded = FALSE;
3757 consdata->implsadded = FALSE;
3758 consdata->rangedrowpropagated = 0;
3759 consdata->merged = FALSE;
3760
3761 if( consdata->nvars == 1 )
3762 {
3763 consdata->indexsorted = TRUE;
3764 consdata->coefsorted = TRUE;
3765 }
3766 else
3767 {
3769 {
3770 consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3771 consdata->coefsorted = FALSE;
3772 }
3773 else
3774 {
3775 consdata->indexsorted = FALSE;
3776 consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3777 }
3778 }
3779
3780 /* update hascontvar and hasnonbinvar flags */
3781 if( consdata->hasnonbinvalid && !consdata->hascontvar )
3782 {
3783 SCIP_VARTYPE vartype = SCIPvarGetType(var);
3784
3785 if( vartype != SCIP_VARTYPE_BINARY )
3786 {
3787 consdata->hasnonbinvar = TRUE;
3788
3789 if( vartype == SCIP_VARTYPE_CONTINUOUS )
3790 consdata->hascontvar = TRUE;
3791 }
3792 }
3793
3794 /* add the new coefficient to the LP row */
3795 if( consdata->row != NULL )
3796 {
3797 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3798 }
3799
3800 return SCIP_OKAY;
3801}
3802
3803/** deletes coefficient at given position from linear constraint data */
3804static
3806 SCIP* scip, /**< SCIP data structure */
3807 SCIP_CONS* cons, /**< linear constraint */
3808 int pos /**< position of coefficient to delete */
3809 )
3810{
3811 SCIP_CONSDATA* consdata;
3812 SCIP_VAR* var;
3813 SCIP_Real val;
3814
3815 assert(scip != NULL);
3816 assert(cons != NULL);
3817
3818 consdata = SCIPconsGetData(cons);
3819 assert(consdata != NULL);
3820 assert(0 <= pos && pos < consdata->nvars);
3821
3822 var = consdata->vars[pos];
3823 val = consdata->vals[pos];
3824 assert(var != NULL);
3825
3826 /* remove rounding locks for deleted variable with non-zero coefficient */
3827 if( !SCIPisZero(scip, val) )
3828 {
3829 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3830 }
3831
3832 /* if we are in transformed problem, delete the event data of the variable */
3833 if( SCIPconsIsTransformed(cons) )
3834 {
3835 SCIP_CONSHDLR* conshdlr;
3836 SCIP_CONSHDLRDATA* conshdlrdata;
3837
3838 /* check for event handler */
3839 conshdlr = SCIPconsGetHdlr(cons);
3840 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3841 assert(conshdlrdata != NULL);
3842 assert(conshdlrdata->eventhdlr != NULL);
3843
3844 /* drop bound change events of variable */
3845 if( consdata->eventdata != NULL )
3846 {
3847 SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3848 assert(consdata->eventdata[pos] == NULL);
3849 }
3850 }
3851
3852 /* move the last variable to the free slot */
3853 if( pos != consdata->nvars - 1 )
3854 {
3855 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3856 consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3857
3858 if( consdata->eventdata != NULL )
3859 {
3860 consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3861 assert(consdata->eventdata[pos] != NULL);
3862 consdata->eventdata[pos]->varpos = pos;
3863 }
3864
3865 consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3866 consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3867 }
3868 consdata->nvars--;
3869
3870 /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3871 * of the remaining variable, or give exactly 0.0)
3872 */
3873 if( consdata->nvars <= 1 )
3875 else
3876 {
3877 /* if we are in transformed problem, update minimum and maximum activities */
3878 if( SCIPconsIsTransformed(cons) && !SCIPisZero(scip, val) )
3879 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3880 }
3881
3882 /* mark the constraint for propagation */
3883 if( SCIPconsIsTransformed(cons) )
3884 {
3886 }
3887
3888 consdata->boundstightened = 0;
3889 consdata->presolved = FALSE;
3890 consdata->validsignature = FALSE;
3891 consdata->changed = TRUE;
3892 consdata->normalized = FALSE;
3893 consdata->upgradetried = FALSE;
3894 consdata->cliquesadded = FALSE;
3895 consdata->implsadded = FALSE;
3896 consdata->rangedrowpropagated = 0;
3897
3898 /* check if hasnonbinvar flag might be incorrect now */
3899 if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3900 {
3901 consdata->hasnonbinvalid = FALSE;
3902 }
3903
3904 /* delete coefficient from the LP row */
3905 if( consdata->row != NULL )
3906 {
3907 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3908 }
3909
3910 /* release variable */
3911 SCIP_CALL( SCIPreleaseVar(scip, &var) );
3912
3913 return SCIP_OKAY;
3914}
3915
3916/** changes coefficient value at given position of linear constraint data */
3917static
3919 SCIP* scip, /**< SCIP data structure */
3920 SCIP_CONS* cons, /**< linear constraint */
3921 int pos, /**< position of coefficient to delete */
3922 SCIP_Real newval /**< new value of coefficient */
3923 )
3924{
3925 SCIP_CONSDATA* consdata;
3926 SCIP_VAR* var;
3927 SCIP_Real val;
3928 SCIP_Bool locked;
3929 int i;
3930
3931 assert(scip != NULL);
3932 assert(cons != NULL);
3933 consdata = SCIPconsGetData(cons);
3934 assert(consdata != NULL);
3935 assert(0 <= pos && pos < consdata->nvars);
3936 var = consdata->vars[pos];
3937 assert(var != NULL);
3938 assert(SCIPvarIsTransformed(var) == SCIPconsIsTransformed(cons));
3939 val = consdata->vals[pos];
3940 assert(!SCIPisZero(scip, val) || !SCIPisZero(scip, newval));
3941
3942 locked = FALSE;
3943 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3944 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3945
3946 /* if necessary, update the rounding locks of the variable */
3947 if( locked && ( !SCIPisNegative(scip, val) || !SCIPisNegative(scip, newval) )
3948 && ( !SCIPisPositive(scip, val) || !SCIPisPositive(scip, newval) ) )
3949 {
3950 assert(SCIPconsIsTransformed(cons));
3951
3952 /* remove rounding locks for variable with old non-zero coefficient */
3953 if( !SCIPisZero(scip, val) )
3954 {
3955 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3956 }
3957
3958 /* install rounding locks for variable with new non-zero coefficient */
3959 if( !SCIPisZero(scip, newval) )
3960 {
3961 SCIP_CALL( lockRounding(scip, cons, var, newval) );
3962 }
3963 }
3964
3965 /* change the value */
3966 consdata->vals[pos] = newval;
3967
3968 if( consdata->coefsorted )
3969 {
3970 if( pos > 0 )
3971 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
3972 if( consdata->coefsorted && pos < consdata->nvars - 1 )
3973 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
3974 }
3975
3976 /* update minimum and maximum activities */
3977 if( SCIPconsIsTransformed(cons) )
3978 {
3979 if( SCIPisZero(scip, val) )
3980 consdataUpdateAddCoef(scip, consdata, var, newval, TRUE);
3981 else if( SCIPisZero(scip, newval) )
3982 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3983 else
3984 consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
3985 }
3986
3987 /* mark the constraint for propagation */
3988 if( SCIPconsIsTransformed(cons) )
3989 {
3991 }
3992
3993 consdata->boundstightened = 0;
3994 consdata->presolved = FALSE;
3995 consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
3996 consdata->changed = TRUE;
3997 consdata->normalized = FALSE;
3998 consdata->upgradetried = FALSE;
3999 consdata->cliquesadded = FALSE;
4000 consdata->implsadded = FALSE;
4001 consdata->rangedrowpropagated = 0;
4002
4003 return SCIP_OKAY;
4004}
4005
4006/** scales a linear constraint with a constant scalar */
4007static
4009 SCIP* scip, /**< SCIP data structure */
4010 SCIP_CONS* cons, /**< linear constraint to scale */
4011 SCIP_Real scalar /**< value to scale constraint with */
4012 )
4013{
4014 SCIP_CONSDATA* consdata;
4015 SCIP_Real newval;
4016 SCIP_Real absscalar;
4017 int i;
4018
4019 assert(scip != NULL);
4020 assert(cons != NULL);
4021
4022 consdata = SCIPconsGetData(cons);
4023 assert(consdata != NULL);
4024 assert(consdata->row == NULL);
4025 assert(scalar != 1.0);
4026
4027 if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4028 || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4029 {
4030 SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4031 SCIPconsGetName(cons), scalar);
4032
4033 return SCIP_OKAY;
4034 }
4035
4036 /* scale the coefficients */
4037 for( i = consdata->nvars - 1; i >= 0; --i )
4038 {
4039 newval = scalar * consdata->vals[i];
4040
4041 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4042 * flooring down our new value
4043 */
4044 if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4045 newval = SCIPfeasFloor(scip, newval + 0.5);
4046
4047 if( SCIPisZero(scip, newval) )
4048 {
4049 SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4050 consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4051 SCIP_CALL( delCoefPos(scip, cons, i) );
4052 }
4053 else
4054 consdata->vals[i] = newval;
4055 }
4056
4057 /* scale the sides */
4058 if( scalar < 0.0 )
4059 {
4060 SCIP_Real lhs;
4061
4062 lhs = consdata->lhs;
4063 consdata->lhs = -consdata->rhs;
4064 consdata->rhs = -lhs;
4065 }
4066 absscalar = REALABS(scalar);
4067 if( !SCIPisInfinity(scip, -consdata->lhs) )
4068 {
4069 newval = absscalar * consdata->lhs;
4070
4071 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4072 * flooring down our new value
4073 */
4074 if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4075 consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4076 else
4077 consdata->lhs = newval;
4078 }
4079 if( !SCIPisInfinity(scip, consdata->rhs) )
4080 {
4081 newval = absscalar * consdata->rhs;
4082
4083 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4084 * our new value
4085 */
4086 if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4087 consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4088 else
4089 consdata->rhs = newval;
4090 }
4091
4093 consdata->cliquesadded = FALSE;
4094 consdata->implsadded = FALSE;
4095
4096 return SCIP_OKAY;
4097}
4098
4099/** perform deletion of variables in all constraints of the constraint handler */
4100static
4102 SCIP* scip, /**< SCIP data structure */
4103 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4104 SCIP_CONS** conss, /**< array of constraints */
4105 int nconss /**< number of constraints */
4106 )
4107{
4108 SCIP_CONSDATA* consdata;
4109 int i;
4110 int v;
4111
4112 assert(scip != NULL);
4113 assert(conshdlr != NULL);
4114 assert(conss != NULL);
4115 assert(nconss >= 0);
4116 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4117
4118 /* iterate over all constraints */
4119 for( i = 0; i < nconss; i++ )
4120 {
4121 consdata = SCIPconsGetData(conss[i]);
4122
4123 /* constraint is marked, that some of its variables were deleted */
4124 if( consdata->varsdeleted )
4125 {
4126 /* iterate over all variables of the constraint and delete them from the constraint */
4127 for( v = consdata->nvars - 1; v >= 0; --v )
4128 {
4129 if( SCIPvarIsDeleted(consdata->vars[v]) )
4130 {
4131 SCIP_CALL( delCoefPos(scip, conss[i], v) );
4132 }
4133 }
4134 consdata->varsdeleted = FALSE;
4135 }
4136 }
4137
4138 return SCIP_OKAY;
4139}
4140
4141
4142/** normalizes a linear constraint with the following rules:
4143 * - if all coefficients have them same absolute value, change them to (-)1.0
4144 * - multiplication with +1 or -1:
4145 * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4146 * if the current rule doesn't determine the sign):
4147 * 1. the right hand side must not be negative
4148 * 2. the right hand side must not be infinite
4149 * 3. the absolute value of the right hand side must be greater than that of the left hand side
4150 * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4151 * 5. multiply with +1
4152 * - rationals to integrals
4153 * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4154 * by the smallest common multiple of all denominators to get integral coefficients.
4155 * Forbid large denominators due to numerical stability.
4156 * - division by greatest common divisor
4157 * If all coefficients are integral, divide them by the greatest common divisor.
4158 */
4159static
4161 SCIP* scip, /**< SCIP data structure */
4162 SCIP_CONS* cons, /**< linear constraint to normalize */
4163 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4164 )
4165{
4166 SCIP_CONSDATA* consdata;
4167 SCIP_Real* vals;
4168 SCIP_Longint scm;
4169 SCIP_Longint nominator;
4170 SCIP_Longint denominator;
4171 SCIP_Longint gcd;
4172 SCIP_Longint maxmult;
4173 SCIP_Real epsilon;
4174 SCIP_Real feastol;
4175 SCIP_Real maxabsval;
4176 SCIP_Real minabsval;
4177 SCIP_Bool success;
4178 SCIP_Bool onlyintegral;
4179 int nvars;
4180 int mult;
4181 int nposcoeffs;
4182 int nnegcoeffs;
4183 int i;
4184
4185 assert(scip != NULL);
4186 assert(cons != NULL);
4187 assert(infeasible != NULL);
4188
4189 *infeasible = FALSE;
4190
4191 /* we must not change a modifiable constraint in any way */
4192 if( SCIPconsIsModifiable(cons) )
4193 return SCIP_OKAY;
4194
4195 /* get constraint data */
4196 consdata = SCIPconsGetData(cons);
4197 assert(consdata != NULL);
4198
4199 /* check, if the constraint is already normalized */
4200 if( consdata->normalized )
4201 return SCIP_OKAY;
4202
4203 /* get coefficient arrays */
4204 vals = consdata->vals;
4205 nvars = consdata->nvars;
4206 assert(nvars == 0 || vals != NULL);
4207
4208 if( nvars == 0 )
4209 {
4210 consdata->normalized = TRUE;
4211 return SCIP_OKAY;
4212 }
4213
4214 assert(vals != NULL);
4215
4216 /* get maximum and minimum absolute coefficient */
4217 maxabsval = consdataGetMaxAbsval(consdata);
4218 minabsval = consdataGetMinAbsval(consdata);
4219
4220 /* return if scaling by maxval will eliminate coefficients */
4221 if( SCIPisZero(scip, minabsval/maxabsval) )
4222 return SCIP_OKAY;
4223
4224 /* return if scaling by maxval will eliminate or generate non-zero sides */
4225 if( !SCIPisInfinity(scip, consdata->lhs) && SCIPisFeasZero(scip, consdata->lhs) != SCIPisFeasZero(scip, consdata->lhs/maxabsval) )
4226 return SCIP_OKAY;
4227 if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasZero(scip, consdata->rhs) != SCIPisFeasZero(scip, consdata->rhs/maxabsval) )
4228 return SCIP_OKAY;
4229
4230 /* check if not all absolute coefficients are near 1.0 but scaling could do */
4231 if( SCIPisLT(scip, minabsval, 1.0) != SCIPisGT(scip, maxabsval, 1.0) )
4232 {
4233 SCIP_Real scalar;
4234
4235 /* calculate scale of the average minimum and maximum absolute coefficient to 1.0 */
4236 scalar = 2.0 / (minabsval + maxabsval);
4237
4238 /* check if all scaled absolute coefficients are near 1.0
4239 * we can relax EQ(x,1.0) to LE(x,1.0), as LT(x,1.0) is not possible
4240 */
4241 if( SCIPisLE(scip, scalar * maxabsval, 1.0) )
4242 {
4243 SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4245 SCIP_CALL( scaleCons(scip, cons, scalar) );
4246
4247 /* get new consdata information, because scaleCons() might have deleted variables */
4248 vals = consdata->vals;
4249 nvars = consdata->nvars;
4250
4251 assert(nvars == 0 || vals != NULL);
4252 }
4253 }
4254
4255 /* nvars might have changed */
4256 if( nvars == 0 )
4257 {
4258 consdata->normalized = TRUE;
4259 return SCIP_OKAY;
4260 }
4261
4262 assert(vals != NULL);
4263
4264 /* calculate the maximal multiplier for common divisor calculation:
4265 * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4266 * which means, a value of feastol/epsilon should be used as maximal multiplier;
4267 * additionally, we don't want to scale the constraint if this would lead to too
4268 * large coefficients
4269 */
4270 epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4271 feastol = SCIPfeastol(scip);
4272 maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4273
4274 if( !consdata->hasnonbinvalid )
4275 consdataCheckNonbinvar(consdata);
4276
4277 /* get maximum absolute coefficient */
4278 maxabsval = consdataGetMaxAbsval(consdata);
4279
4280 /* if all variables are of integral type we will allow a greater multiplier */
4281 if( !consdata->hascontvar )
4282 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4283 else
4284 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4285
4286 /*
4287 * multiplication with +1 or -1
4288 */
4289 mult = 0;
4290
4291 /* 1. the right hand side must not be negative */
4292 if( SCIPisPositive(scip, consdata->lhs) )
4293 mult = +1;
4294 else if( SCIPisNegative(scip, consdata->rhs) )
4295 mult = -1;
4296
4297 if( mult == 0 )
4298 {
4299 /* 2. the right hand side must not be infinite */
4300 if( SCIPisInfinity(scip, -consdata->lhs) )
4301 mult = +1;
4302 else if( SCIPisInfinity(scip, consdata->rhs) )
4303 mult = -1;
4304 }
4305
4306 if( mult == 0 )
4307 {
4308 /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4309 if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4310 mult = +1;
4311 else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4312 mult = -1;
4313 }
4314
4315 if( mult == 0 )
4316 {
4317 /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4318 nposcoeffs = 0;
4319 nnegcoeffs = 0;
4320 for( i = 0; i < nvars; ++i )
4321 {
4322 if( vals[i] > 0.0 )
4323 nposcoeffs++;
4324 else
4325 nnegcoeffs++;
4326 }
4327 if( nposcoeffs > nnegcoeffs )
4328 mult = +1;
4329 else if( nposcoeffs < nnegcoeffs )
4330 mult = -1;
4331 }
4332
4333 if( mult == 0 )
4334 {
4335 /* 5. multiply with +1 */
4336 mult = +1;
4337 }
4338
4339 assert(mult == +1 || mult == -1);
4340 if( mult == -1 )
4341 {
4342 /* scale the constraint with -1 */
4343 SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4345 SCIP_CALL( scaleCons(scip, cons, -1.0) );
4346
4347 /* scalecons() can delete variables, but scaling with -1 should not do that */
4348 assert(nvars == consdata->nvars);
4349 }
4350
4351 /*
4352 * rationals to integrals
4353 *
4354 * @todo try scaling only on behalf of non-continuous variables
4355 */
4356 success = TRUE;
4357 scm = 1;
4358 for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4359 {
4360 if( !SCIPisIntegral(scip, vals[i]) )
4361 {
4362 /* epsilon has been slightly decreased above - to be on the safe side */
4363 success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4364 if( success )
4365 scm = SCIPcalcSmaComMul(scm, denominator);
4366 }
4367 }
4368 assert(scm >= 1);
4369
4370 /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4371 * their greatest common divisor
4372 */
4373 onlyintegral = TRUE;
4374 if( scm == 1 )
4375 {
4376 for( i = nvars - 1; i >= 0; --i )
4377 {
4378 if( !SCIPisIntegral(scip, vals[i]) )
4379 {
4380 onlyintegral = FALSE;
4381 break;
4382 }
4383 }
4384 }
4385
4386 success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4387 if( success && scm != 1 )
4388 {
4389 /* scale the constraint with the smallest common multiple of all denominators */
4390 SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4392 SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4393
4394 if( consdata->validmaxabsval )
4395 {
4396 consdata->maxabsval *= REALABS((SCIP_Real)scm);
4397 if( !SCIPisIntegral(scip, consdata->maxabsval) )
4398 {
4399 consdata->validmaxabsval = FALSE;
4400 consdata->maxabsval = SCIP_INVALID;
4401 consdataCalcMaxAbsval(consdata);
4402 }
4403 }
4404
4405 if( consdata->validminabsval )
4406 {
4407 consdata->minabsval *= REALABS((SCIP_Real)scm);
4408 if( !SCIPisIntegral(scip, consdata->minabsval) )
4409 {
4410 consdata->validminabsval = FALSE;
4411 consdata->minabsval = SCIP_INVALID;
4412 consdataCalcMinAbsval(consdata);
4413 }
4414 }
4415
4416 /* get new consdata information, because scalecons() might have deleted variables */
4417 vals = consdata->vals;
4418 nvars = consdata->nvars;
4419 assert(nvars == 0 || vals != NULL);
4420 }
4421
4422 /*
4423 * division by greatest common divisor
4424 */
4425 if( success && nvars >= 1 )
4426 {
4427 /* all coefficients are integral: divide them by their greatest common divisor */
4428 assert(SCIPisIntegral(scip, vals[0]));
4429
4430 gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4431 for( i = 1; i < nvars && gcd > 1; ++i )
4432 {
4433 assert(SCIPisIntegral(scip, vals[i]));
4434 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4435 }
4436
4437 if( gcd > 1 )
4438 {
4439 /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4440 if( !consdata->hascontvar && onlyintegral )
4441 {
4442 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4443 {
4444 *infeasible = TRUE;
4445
4446 SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4448
4449 return SCIP_OKAY;
4450 }
4451 }
4452
4453 /* divide the constraint by the greatest common divisor of the coefficients */
4454 SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4456 SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4457
4458 if( consdata->validmaxabsval )
4459 {
4460 consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4461 }
4462 if( consdata->validminabsval )
4463 {
4464 consdata->minabsval /= REALABS((SCIP_Real)gcd);
4465 }
4466 }
4467 }
4468
4469 /* mark constraint to be normalized */
4470 consdata->normalized = TRUE;
4471
4472 SCIPdebugMsg(scip, "normalized constraint:\n");
4474
4475 return SCIP_OKAY;
4476}
4477
4478/** replaces multiple occurrences of a variable by a single non-zero coefficient */
4479static
4481 SCIP* scip, /**< SCIP data structure */
4482 SCIP_CONS* cons /**< linear constraint */
4483 )
4484{
4485 SCIP_CONSDATA* consdata;
4486 SCIP_VAR* var;
4487 SCIP_Real valsum;
4488 int v;
4489
4490 assert(scip != NULL);
4491 assert(cons != NULL);
4492
4493 consdata = SCIPconsGetData(cons);
4494 assert(consdata != NULL);
4495
4496 if( consdata->merged )
4497 return SCIP_OKAY;
4498
4499 /* sort the constraint */
4500 SCIP_CALL( consdataSort(scip, consdata) );
4501
4502 v = consdata->nvars - 1;
4503
4504 /* go backwards through the constraint looking for multiple occurrences of the same variable;
4505 * backward direction is necessary, since delCoefPos() modifies the given position and
4506 * the subsequent ones
4507 */
4508 while( v >= 0 )
4509 {
4510 var = consdata->vars[v];
4511 valsum = consdata->vals[v];
4512
4513 /* sum multiple occurrences */
4514 while( v >= 1 && consdata->vars[v-1] == var )
4515 {
4516 SCIP_CALL( delCoefPos(scip, cons, v) );
4517 --v;
4518 valsum += consdata->vals[v];
4519 }
4520
4521 assert(consdata->vars[v] == var);
4522
4523 /* modify the last existing occurrence of the variable */
4524 if( SCIPisZero(scip, valsum) )
4525 {
4526 SCIP_CALL( delCoefPos(scip, cons, v) );
4527 }
4528 else if( valsum != consdata->vals[v] ) /*lint !e777*/
4529 {
4530 SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4531 }
4532
4533 --v;
4534 }
4535
4536 consdata->merged = TRUE;
4537
4538 return SCIP_OKAY;
4539}
4540
4541/** replaces all fixed and aggregated variables by their non-fixed counterparts */
4542static
4544 SCIP* scip, /**< SCIP data structure */
4545 SCIP_CONS* cons, /**< linear constraint */
4546 SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4547 * information is not needed; in this case, we apply all fixings
4548 * instead of stopping after the first infeasible one */
4549 )
4550{
4551 SCIP_CONSDATA* consdata;
4552 int v;
4553
4554 assert(scip != NULL);
4555 assert(cons != NULL);
4556
4557 if( infeasible != NULL )
4558 *infeasible = FALSE;
4559
4560 consdata = SCIPconsGetData(cons);
4561 assert(consdata != NULL);
4562
4563 if( consdata->eventdata == NULL )
4564 {
4565 SCIP_CONSHDLR* conshdlr;
4566 SCIP_CONSHDLRDATA* conshdlrdata;
4567
4568 conshdlr = SCIPconsGetHdlr(cons);
4569 assert(conshdlr != NULL);
4570
4571 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4572 assert(conshdlrdata != NULL);
4573
4574 /* catch bound change events of variables */
4575 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4576 assert(consdata->eventdata != NULL);
4577 }
4578
4579 if( !consdata->removedfixings )
4580 {
4581 SCIP_Real lhssubtrahend;
4582 SCIP_Real rhssubtrahend;
4583
4584 /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4585 * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4586 */
4587 assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4588
4589 lhssubtrahend = 0.0;
4590 rhssubtrahend = 0.0;
4591
4592 SCIPdebugMsg(scip, "applying fixings:\n");
4594
4595 v = 0;
4596 while( v < consdata->nvars )
4597 {
4598 SCIP_VAR* var = consdata->vars[v];
4599 SCIP_Real scalar = consdata->vals[v];
4600 SCIP_Real constant = 0.0;
4601 assert(SCIPvarIsTransformed(var));
4602
4603 SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
4604
4605 switch( SCIPvarGetStatus(var) )
4606 {
4608 SCIPerrorMessage("original variable in transformed linear constraint\n");
4609 return SCIP_INVALIDDATA;
4610
4613 SCIPerrorMessage("aggregated variable after resolving linear term\n");
4614 return SCIP_INVALIDDATA;
4615
4618 if( var != consdata->vars[v] )
4619 {
4620 assert(scalar != 0.0);
4621 SCIP_CALL( addCoef(scip, cons, var, scalar) );
4622 SCIP_CALL( delCoefPos(scip, cons, v) );
4623
4624 assert(!SCIPisInfinity(scip, ABS(constant)));
4625 if( !SCIPisInfinity(scip, -consdata->lhs) )
4626 lhssubtrahend += constant;
4627 if( !SCIPisInfinity(scip, consdata->rhs) )
4628 rhssubtrahend += constant;
4629 }
4630 ++v;
4631 break;
4632
4634 if( scalar != 0.0 )
4635 {
4636 SCIP_VAR** aggrvars;
4637 SCIP_Real* aggrscalars;
4638 SCIP_Real aggrconstant;
4639 int naggrvars;
4640 int i;
4641
4643 aggrvars = SCIPvarGetMultaggrVars(var);
4644 aggrscalars = SCIPvarGetMultaggrScalars(var);
4645 aggrconstant = SCIPvarGetMultaggrConstant(var);
4646 naggrvars = SCIPvarGetMultaggrNVars(var);
4647
4648 for( i = 0; i < naggrvars; ++i )
4649 {
4650 SCIP_CALL( addCoef(scip, cons, aggrvars[i], scalar * aggrscalars[i]) );
4651 }
4652
4653 constant += scalar * aggrconstant;
4654 }
4655 /*lint -fallthrough*/
4656
4658 if( !SCIPisInfinity(scip, -consdata->lhs) )
4659 {
4660 if( SCIPisInfinity(scip, ABS(constant)) )
4661 {
4662 /* if lhs gets infinity it means that the problem is infeasible */
4663 if( constant < 0.0 )
4664 {
4666
4667 if( infeasible != NULL )
4668 {
4669 *infeasible = TRUE;
4670 return SCIP_OKAY;
4671 }
4672 }
4673 else
4674 {
4675 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4676 }
4677 }
4678 else
4679 lhssubtrahend += constant;
4680 }
4681 if( !SCIPisInfinity(scip, consdata->rhs) )
4682 {
4683 if( SCIPisInfinity(scip, ABS(constant)) )
4684 {
4685 /* if rhs gets -infinity it means that the problem is infeasible */
4686 if( constant > 0.0 )
4687 {
4688 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4689
4690 if( infeasible != NULL )
4691 {
4692 *infeasible = TRUE;
4693 return SCIP_OKAY;
4694 }
4695 }
4696 else
4697 {
4699 }
4700 }
4701 else
4702 rhssubtrahend += constant;
4703 }
4704 SCIP_CALL( delCoefPos(scip, cons, v) );
4705 break;
4706
4707 default:
4708 SCIPerrorMessage("unknown variable status\n");
4709 SCIPABORT();
4710 return SCIP_INVALIDDATA; /*lint !e527*/
4711 }
4712 }
4713
4714 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4715 {
4716 /* check left hand side of unmodifiable empty constraint with former feasibility tolerance */
4717 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4718 {
4719 if( SCIPisFeasLT(scip, lhssubtrahend, consdata->lhs) )
4720 {
4722
4723 if( infeasible != NULL )
4724 {
4725 *infeasible = TRUE;
4726 return SCIP_OKAY;
4727 }
4728 }
4729 else
4730 {
4731 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4732 }
4733 }
4734 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
4735 * causing wrong fixings of other variables --> better use a real zero here
4736 */
4737 else if( SCIPisGE(scip, ABS(consdata->lhs), 1.0) && SCIPisEQ(scip, lhssubtrahend, consdata->lhs) )
4738 {
4739 SCIP_CALL( chgLhs(scip, cons, 0.0) );
4740 }
4741 else
4742 {
4743 SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4744 }
4745 }
4746 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs) )
4747 {
4748 /* check right hand side of unmodifiable empty constraint with former feasibility tolerance */
4749 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4750 {
4751 if( SCIPisFeasGT(scip, rhssubtrahend, consdata->rhs) )
4752 {
4753 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4754
4755 if( infeasible != NULL )
4756 {
4757 *infeasible = TRUE;
4758 return SCIP_OKAY;
4759 }
4760 }
4761 else
4762 {
4764 }
4765 }
4766 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
4767 * causing wrong fixings of other variables --> better use a real zero here
4768 */
4769 else if( SCIPisGE(scip, ABS(consdata->rhs), 1.0) && SCIPisEQ(scip, rhssubtrahend, consdata->rhs) )
4770 {
4771 SCIP_CALL( chgRhs(scip, cons, 0.0) );
4772 }
4773 else
4774 {
4775 SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4776 }
4777 }
4778 consdata->removedfixings = TRUE;
4779
4780 SCIPdebugMsg(scip, "after fixings:\n");
4782
4783 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4784 * to clean up the constraint
4785 */
4786 SCIP_CALL( mergeMultiples(scip, cons) );
4787
4788 SCIPdebugMsg(scip, "after merging:\n");
4790 }
4791 assert(consdata->removedfixings);
4792
4793#ifndef NDEBUG
4794 /* check, if all fixings are applied */
4795 for( v = 0; v < consdata->nvars; ++v )
4796 assert(SCIPvarIsActive(consdata->vars[v]));
4797#endif
4798
4799 return SCIP_OKAY;
4800}
4801
4802/** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4803 * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4804 * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4805 * conflict detecting constraint by using NULL as inferred variable
4806 */
4807static
4809 SCIP* scip, /**< SCIP data structure */
4810 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4811 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4812 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4813 int inferpos, /**< position of the inferred variable in the vars array */
4814 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4815 )
4816{
4817 SCIP_CONSDATA* consdata;
4818 SCIP_VAR** vars;
4819 SCIP_Real* vals;
4820 int nvars;
4821 int i;
4822
4823 assert(scip != NULL);
4824 assert(cons != NULL);
4825
4826 consdata = SCIPconsGetData(cons);
4827
4828 assert(consdata != NULL);
4829
4830 vars = consdata->vars;
4831 vals = consdata->vals;
4832 nvars = consdata->nvars;
4833
4834 assert(vars != NULL || nvars == 0);
4835 assert(vals != NULL || nvars == 0);
4836
4837 assert(-1 <= inferpos && inferpos < nvars);
4838 assert((infervar == NULL) == (inferpos == -1));
4839 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4840
4841 /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4842 * residual value, depending on whether the left or right hand side is responsible for the bound change:
4843 * - if the right hand side is the reason, the minimal residual activity is responsible
4844 * - if the left hand side is the reason, the maximal residual activity is responsible
4845 */
4846
4847 /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4848 if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4849 {
4850 SCIP_Real minresactivity;
4851 SCIP_Real maxresactivity;
4852 SCIP_Bool ismintight;
4853 SCIP_Bool ismaxtight;
4854 SCIP_Bool isminsettoinfinity;
4855 SCIP_Bool ismaxsettoinfinity;
4856
4857 minresactivity = -SCIPinfinity(scip);
4858 maxresactivity = SCIPinfinity(scip);
4859
4860 /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4861 if( infervar != NULL )
4862 {
4863 assert(vals != NULL); /* for flexelint */
4864 if( reasonisrhs )
4865 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4866 &ismintight, NULL, &isminsettoinfinity, NULL);
4867 else
4868 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4869 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4870 }
4871 else
4872 {
4873 if( reasonisrhs )
4874 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4875 &ismintight, NULL, &isminsettoinfinity, NULL);
4876 else
4877 consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4878 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4879 }
4880
4881 /* we can only do something clever, if the residual activity is finite and not relaxed */
4882 if( (reasonisrhs && !isminsettoinfinity && ismintight) || (!reasonisrhs && !ismaxsettoinfinity && ismaxtight) ) /*lint !e644*/
4883 {
4884 SCIP_Real rescap;
4885 SCIP_Bool resactisinf;
4886
4887 resactisinf = FALSE;
4888
4889 /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4890 * than its inferred bound
4891 */
4892 if( infervar != NULL )
4893 {
4894 assert(vals != NULL); /* for flexelint */
4895
4896 if( reasonisrhs )
4897 {
4898 if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4899 {
4900 consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4901 if( SCIPisInfinity(scip, -minresactivity) )
4902 resactisinf = TRUE;
4903 }
4904 rescap = consdata->rhs - minresactivity;
4905 }
4906 else
4907 {
4908 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4909 {
4910 consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4911 if( SCIPisInfinity(scip, maxresactivity) )
4912 resactisinf = TRUE;
4913 }
4914 rescap = consdata->lhs - maxresactivity;
4915 }
4916
4917 if( reasonisrhs == (vals[inferpos] > 0.0) )
4918 rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4919 else
4920 rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
4921 }
4922 else
4923 rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4924
4925 if( !resactisinf )
4926 {
4927 /* now add bounds as reasons until the residual capacity is exceeded */
4928 for( i = 0; i < nvars; ++i )
4929 {
4930 assert( vars != NULL && vals != NULL ); /* for lint */
4931
4932 /* zero coefficients and the inferred variable can be ignored */
4933 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4934 continue;
4935
4936 /* check if the residual capacity is exceeded */
4937 if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4938 || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4939 break;
4940
4941 /* update the residual capacity due to the local bound of this variable */
4942 if( reasonisrhs == (vals[i] > 0.0) )
4943 {
4944 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4945 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4946 rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4947 }
4948 else
4949 {
4950 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4951 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4952 rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4953 }
4954 }
4955 return SCIP_OKAY;
4956 }
4957 }
4958 }
4959
4960 /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4961 for( i = 0; i < nvars; ++i )
4962 {
4963 assert(vars != NULL); /* for flexelint */
4964 assert(vals != NULL); /* for flexelint */
4965
4966 /* zero coefficients and the inferred variable can be ignored */
4967 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4968 continue;
4969
4970 if( reasonisrhs == (vals[i] > 0.0) )
4971 {
4972 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4973 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4974 }
4975 else
4976 {
4977 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
4978 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4979 }
4980 }
4981
4982 return SCIP_OKAY;
4983}
4984
4985/** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
4986 * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
4987 * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
4988 */
4989static
4991 SCIP* scip, /**< SCIP data structure */
4992 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4993 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4994 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4995 int inferpos /**< position of the inferred variable in the vars array, or -1 */
4996 )
4997{
4998 SCIP_CONSDATA* consdata;
4999 SCIP_VAR** vars;
5000 int nvars;
5001 int v;
5002
5003 assert(scip != NULL);
5004 assert(cons != NULL);
5005
5006 consdata = SCIPconsGetData(cons);
5007 assert(consdata != NULL);
5008 vars = consdata->vars;
5009 nvars = consdata->nvars;
5010 assert(vars != NULL || nvars == 0);
5011 assert(-1 <= inferpos && inferpos < nvars);
5012 assert((infervar == NULL) == (inferpos == -1));
5013 assert(inferpos == -1 || vars != NULL);
5014 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5015
5016 /* collect all fixed variables */
5017 for( v = nvars - 1; v >= 0; --v )
5018 {
5019 assert(vars != NULL); /* for flexelint */
5020
5021 /* need to add old bounds before propagation of inferrence variable */
5022 if( vars[v] == infervar )
5023 {
5024 assert(vars[v] != NULL);
5025
5026 if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5027 {
5028 /* @todo get boundchange index before this last boundchange and correct the index */
5029 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5030 }
5031
5032 if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5033 {
5034 /* @todo get boundchange index before this last boundchange and correct the index */
5035 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5036 }
5037
5038 continue;
5039 }
5040
5041 /* check for fixed variables */
5042 if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5043 {
5044 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5045 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5046 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5047 }
5048 }
5049
5050 return SCIP_OKAY;
5051}
5052
5053/** add reasoning variables to conflict candidate queue which led to the conflict */
5054static
5056 SCIP* scip, /**< SCIP data structure */
5057 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5058 int nvars, /**< number of variables reasoning the infeasibility */
5059 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5060 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5061 )
5062{
5063 int v;
5064
5065 assert(scip != NULL);
5066
5067 /* collect all variables for which the local bounds differ from their global bounds */
5068 for( v = nvars - 1; v >= 0; --v )
5069 {
5070 assert(vars != NULL);
5071
5072 /* check for local bound changes variables */
5073 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5074 {
5075 /* add conflict bound */
5076 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5077 }
5078
5079 if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5080 {
5081 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5082 }
5083 }
5084
5085 if( var != NULL )
5086 {
5087 if( bound < SCIPvarGetLbLocal(var) )
5088 {
5089 SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5090 }
5091
5092 if( bound > SCIPvarGetUbLocal(var) )
5093 {
5094 SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5095 }
5096 }
5097
5098 return SCIP_OKAY;
5099}
5100
5101/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5102 * propagation rule (see propagateCons()):
5103 * (1) activity residuals of all other variables tighten bounds of single variable
5104 */
5105static
5107 SCIP* scip, /**< SCIP data structure */
5108 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5109 SCIP_VAR* infervar, /**< variable that was deduced */
5110 INFERINFO inferinfo, /**< inference information */
5111 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5112 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5113 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5114 )
5115{
5116 SCIP_CONSDATA* consdata;
5117 SCIP_VAR** vars;
5118#ifndef NDEBUG
5119 SCIP_Real* vals;
5120#endif
5121 int nvars;
5122 int inferpos;
5123
5124 assert(scip != NULL);
5125 assert(cons != NULL);
5126 assert(result != NULL);
5127
5128 consdata = SCIPconsGetData(cons);
5129 assert(consdata != NULL);
5130 vars = consdata->vars;
5131 nvars = consdata->nvars;
5132#ifndef NDEBUG
5133 vals = consdata->vals;
5134 assert(vars != NULL);
5135 assert(vals != NULL);
5136#endif
5137
5138 /* get the position of the inferred variable in the vars array */
5139 inferpos = inferInfoGetPos(inferinfo);
5140 if( inferpos >= nvars || vars[inferpos] != infervar )
5141 {
5142 /* find inference variable in constraint */
5143 /**@todo use a binary search here; the variables can be sorted by variable index */
5144 for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5145 {}
5146 }
5147 assert(inferpos < nvars);
5148 assert(vars[inferpos] == infervar);
5149 assert(!SCIPisZero(scip, vals[inferpos]));
5150
5151 switch( inferInfoGetProprule(inferinfo) )
5152 {
5153 case PROPRULE_1_RHS:
5154 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5155 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5156 * domain in order to not exceed the right hand side of the inequality
5157 */
5158 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5159 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5160 *result = SCIP_SUCCESS;
5161 break;
5162
5163 case PROPRULE_1_LHS:
5164 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5165 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5166 * domain in order to not fall below the left hand side of the inequality
5167 */
5168 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5169 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5170 *result = SCIP_SUCCESS;
5171 break;
5172
5174 /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5175 * the given inference variable to their bounds in this given ranged row
5176 */
5177
5178 /* check that we really have a ranged row here */
5179 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5180 SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5181 *result = SCIP_SUCCESS;
5182 break;
5183
5184 case PROPRULE_INVALID:
5185 default:
5186 SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5187 inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5188 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5189 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5190 SCIPinfoMessage(scip, NULL, ";\n");
5191 return SCIP_INVALIDDATA;
5192 }
5193
5194 return SCIP_OKAY;
5195}
5196
5197/** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5198static
5200 SCIP* scip, /**< SCIP data structure */
5201 SCIP_CONS* cons, /**< conflict detecting constraint */
5202 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5203 )
5204{
5205 /* conflict analysis can only be applied in solving stage and if it is turned on */
5207 return SCIP_OKAY;
5208
5209 /* initialize conflict analysis */
5211
5212 /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5213 SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5214
5215 /* analyze the conflict */
5217
5218 return SCIP_OKAY;
5219}
5220
5221/** check if there is any hope of tightening some bounds */
5222static
5224 SCIP_CONS* cons /**< linear constraint */
5225 )
5226{
5227 SCIP_CONSDATA* consdata;
5228 int infcountmin;
5229 int infcountmax;
5230
5231 consdata = SCIPconsGetData(cons);
5232 assert(consdata != NULL);
5233
5234 infcountmin = consdata->minactivityneginf
5235 + consdata->minactivityposinf
5236 + consdata->minactivityneghuge
5237 + consdata->minactivityposhuge;
5238 infcountmax = consdata->maxactivityneginf
5239 + consdata->maxactivityposinf
5240 + consdata->maxactivityneghuge
5241 + consdata->maxactivityposhuge;
5242
5243 if( infcountmin > 1 && infcountmax > 1 )
5244 return FALSE;
5245
5246 return TRUE;
5247}
5248
5249/** tighten upper bound */
5250static
5252 SCIP* scip, /**< SCIP data structure */
5253 SCIP_CONS* cons, /**< linear constraint */
5254 int pos, /**< variable position */
5255 PROPRULE proprule, /**< propagation rule that deduced the value */
5256 SCIP_Real newub, /**< new upper bound */
5257 SCIP_Real oldub, /**< old upper bound */
5258 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5259 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5260 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5261 )
5262{
5263 SCIP_CONSDATA* consdata;
5264 SCIP_VAR* var;
5265 SCIP_Real lb;
5266 SCIP_Bool infeasible;
5267 SCIP_Bool tightened;
5268
5269 assert(cons != NULL);
5270 assert(!SCIPisInfinity(scip, newub));
5271
5272 consdata = SCIPconsGetData(cons);
5273 assert(consdata != NULL);
5274 var = consdata->vars[pos];
5275 assert(var != NULL);
5276
5277 lb = SCIPvarGetLbLocal(var);
5278 newub = SCIPadjustedVarUb(scip, var, newub);
5279
5280 if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5281 {
5282 SCIP_VARTYPE vartype;
5283
5284 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5285 SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5286 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5287
5288 vartype = SCIPvarGetType(var);
5289
5290 /* tighten upper bound */
5291 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5292
5293 if( infeasible )
5294 {
5295 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5296 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5297
5298 /* analyze conflict */
5300
5301 *cutoff = TRUE;
5302 }
5303 else if( tightened )
5304 {
5305 assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5306 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5307 SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5308
5309 (*nchgbds)++;
5310
5311 /* if variable type was changed we might be able to upgrade the constraint */
5312 if( vartype != SCIPvarGetType(var) )
5313 consdata->upgradetried = FALSE;
5314 }
5315 }
5316 return SCIP_OKAY;
5317}
5318
5319/** tighten lower bound */
5320static
5322 SCIP* scip, /**< SCIP data structure */
5323 SCIP_CONS* cons, /**< linear constraint */
5324 int pos, /**< variable position */
5325 PROPRULE proprule, /**< propagation rule that deduced the value */
5326 SCIP_Real newlb, /**< new lower bound */
5327 SCIP_Real oldlb, /**< old lower bound */
5328 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5329 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5330 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5331 )
5332{
5333 SCIP_CONSDATA* consdata;
5334 SCIP_VAR* var;
5335 SCIP_Real ub;
5336 SCIP_Bool infeasible;
5337 SCIP_Bool tightened;
5338
5339 assert(cons != NULL);
5340 assert(!SCIPisInfinity(scip, newlb));
5341
5342 consdata = SCIPconsGetData(cons);
5343 assert(consdata != NULL);
5344 var = consdata->vars[pos];
5345 assert(var != NULL);
5346
5347 ub = SCIPvarGetUbLocal(var);
5348 newlb = SCIPadjustedVarLb(scip, var, newlb);
5349
5350 if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5351 {
5352 SCIP_VARTYPE vartype;
5353
5354 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5355 SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5356 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5357
5358 vartype = SCIPvarGetType(var);
5359
5360 /* tighten lower bound */
5361 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5362
5363 if( infeasible )
5364 {
5365 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5366 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5367
5368 /* analyze conflict */
5370
5371 *cutoff = TRUE;
5372 }
5373 else if( tightened )
5374 {
5375 assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5376 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5377 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5378
5379 (*nchgbds)++;
5380
5381 /* if variable type was changed we might be able to upgrade the constraint */
5382 if( vartype != SCIPvarGetType(var) )
5383 consdata->upgradetried = FALSE;
5384 }
5385 }
5386 return SCIP_OKAY;
5387}
5388
5389/** tightens bounds of a single variable due to activity bounds (easy case) */
5390static
5392 SCIP* scip, /**< SCIP data structure */
5393 SCIP_CONS* cons, /**< linear constraint */
5394 int pos, /**< position of the variable in the vars array */
5395 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5396 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5397 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5398 )
5399{
5400 SCIP_CONSDATA* consdata;
5401 SCIP_VAR* var;
5402 SCIP_Real val;
5403 SCIP_Real lb;
5404 SCIP_Real ub;
5405 SCIP_Real lhs;
5406 SCIP_Real rhs;
5407
5408 assert(scip != NULL);
5409 assert(cons != NULL);
5410 assert(cutoff != NULL);
5411 assert(nchgbds != NULL);
5412
5413 /* we cannot tighten variables' bounds, if the constraint may be not complete */
5414 if( SCIPconsIsModifiable(cons) )
5415 return SCIP_OKAY;
5416
5417 consdata = SCIPconsGetData(cons);
5418 assert(consdata != NULL);
5419 assert(0 <= pos && pos < consdata->nvars);
5420
5421 *cutoff = FALSE;
5422
5423 var = consdata->vars[pos];
5424 assert(var != NULL);
5425
5426 /* we cannot tighten bounds of multi-aggregated variables */
5428 return SCIP_OKAY;
5429
5430 val = consdata->vals[pos];
5431 lhs = consdata->lhs;
5432 rhs = consdata->rhs;
5433 assert(!SCIPisZero(scip, val));
5434 assert(!SCIPisInfinity(scip, lhs));
5435 assert(!SCIPisInfinity(scip, -rhs));
5436
5437 lb = SCIPvarGetLbLocal(var);
5438 ub = SCIPvarGetUbLocal(var);
5439 assert(SCIPisLE(scip, lb, ub));
5440
5441 /* recompute activities if needed */
5442 if( !consdata->validactivities )
5443 consdataCalcActivities(scip, consdata);
5444 assert(consdata->validactivities);
5445 if( !consdata->validminact )
5447 assert(consdata->validminact);
5448
5449 if( val > 0.0 )
5450 {
5451 /* check, if we can tighten the variable's upper bound */
5452 if( !SCIPisInfinity(scip, rhs) )
5453 {
5454 SCIP_Real slack;
5455 SCIP_Real alpha;
5456
5457 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5458 assert(consdata->validminact);
5459
5460 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5461 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5462 {
5463 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5464 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5465
5466 *cutoff = TRUE;
5467 return SCIP_OKAY;
5468 }
5469
5470 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5471
5472 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5473 * it to zero
5474 */
5475 if( !SCIPisPositive(scip, slack) )
5476 slack = 0.0;
5477
5478 alpha = val * (ub - lb);
5479 assert(!SCIPisNegative(scip, alpha));
5480
5481 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5482 {
5483 SCIP_Real newub;
5484
5485 /* compute new upper bound */
5486 newub = lb + (slack / val);
5487
5488 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5489
5490 if( *cutoff )
5491 {
5492 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5493 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5494
5495 return SCIP_OKAY;
5496 }
5497
5498 /* collect the new upper bound which is needed for the lower bound computation */
5499 ub = SCIPvarGetUbLocal(var);
5500 }
5501 }
5502
5503 /* check, if we can tighten the variable's lower bound */
5504 if( !SCIPisInfinity(scip, -lhs) )
5505 {
5506 SCIP_Real slack;
5507 SCIP_Real alpha;
5508
5509 /* make sure the max activity is reliable */
5510 if( !consdata->validmaxact )
5511 {
5513 }
5514 assert(consdata->validmaxact);
5515
5516 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5517 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5518 {
5519 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5520 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5521
5522 *cutoff = TRUE;
5523 return SCIP_OKAY;
5524 }
5525
5526 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5527
5528 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5529 * it to zero
5530 */
5531 if( !SCIPisPositive(scip, slack) )
5532 slack = 0.0;
5533
5534 alpha = val * (ub - lb);
5535 assert(!SCIPisNegative(scip, alpha));
5536
5537 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5538 {
5539 SCIP_Real newlb;
5540
5541 /* compute new lower bound */
5542 newlb = ub - (slack / val);
5543
5544 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5545
5546 if( *cutoff )
5547 {
5548 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5549 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5550
5551 return SCIP_OKAY;
5552 }
5553 }
5554 }
5555 }
5556 else
5557 {
5558 /* check, if we can tighten the variable's lower bound */
5559 if( !SCIPisInfinity(scip, rhs) )
5560 {
5561 SCIP_Real slack;
5562 SCIP_Real alpha;
5563
5564 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5565 assert(consdata->validminact);
5566
5567 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5568 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5569 {
5570 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5571 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5572
5573 *cutoff = TRUE;
5574 return SCIP_OKAY;
5575 }
5576
5577 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5578
5579 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5580 * it to zero
5581 */
5582 if( !SCIPisPositive(scip, slack) )
5583 slack = 0.0;
5584
5585 alpha = val * (lb - ub);
5586 assert(!SCIPisNegative(scip, alpha));
5587
5588 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5589 {
5590 SCIP_Real newlb;
5591
5592 /* compute new lower bound */
5593 newlb = ub + slack / val;
5594
5595 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5596
5597 if( *cutoff )
5598 {
5599 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5600 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5601
5602 return SCIP_OKAY;
5603 }
5604 /* collect the new lower bound which is needed for the upper bound computation */
5605 lb = SCIPvarGetLbLocal(var);
5606 }
5607 }
5608
5609 /* check, if we can tighten the variable's upper bound */
5610 if( !SCIPisInfinity(scip, -lhs) )
5611 {
5612 SCIP_Real slack;
5613 SCIP_Real alpha;
5614
5615 /* make sure the max activity is reliable */
5616 if( !consdata->validmaxact )
5617 {
5619 }
5620 assert(consdata->validmaxact);
5621
5622 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5623 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5624 {
5625 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5626 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5627
5628 *cutoff = TRUE;
5629 return SCIP_OKAY;
5630 }
5631
5632 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5633
5634 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5635 * it to zero
5636 */
5637 if( !SCIPisPositive(scip, slack) )
5638 slack = 0.0;
5639
5640 alpha = val * (lb - ub);
5641 assert(!SCIPisNegative(scip, alpha));
5642
5643 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5644 {
5645 SCIP_Real newub;
5646
5647 /* compute new upper bound */
5648 newub = lb - (slack / val);
5649
5650 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5651
5652 if( *cutoff )
5653 {
5654 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5655 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5656
5657 return SCIP_OKAY;
5658 }
5659 }
5660 }
5661 }
5662
5663 return SCIP_OKAY;
5664}
5665
5666/** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5667static
5669 SCIP* scip, /**< SCIP data structure */
5670 SCIP_CONS* cons, /**< conflict detecting constraint */
5671 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5672 int nvars, /**< number of variables reasoning the infeasibility */
5673 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5674 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5675 )
5676{
5677#ifndef NDEBUG
5678 SCIP_CONSDATA* consdata;
5679
5680 assert(scip != NULL);
5681 assert(cons != NULL);
5682
5683 consdata = SCIPconsGetData(cons);
5684 assert(consdata != NULL);
5685 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5686#endif
5687
5688 /* conflict analysis can only be applied in solving stage and if it is turned on */
5690 return SCIP_OKAY;
5691
5692 /* initialize conflict analysis */
5694
5695 /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5697
5698 /* add reasoning variables to conflict candidate queue which led to the conflict */
5699 SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5700
5701 /* analyze the conflict */
5703
5704 return SCIP_OKAY;
5705}
5706
5707/** propagate ranged rows
5708 *
5709 * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5710 * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5711 * variables better.
5712 *
5713 * Example:
5714 * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5715 *
5716 * x3 needs to be a multiple of 3, so the instance is infeasible.
5717 *
5718 * Example:
5719 * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5720 *
5721 * The only possible value for x3 is 2, so the variable will be fixed.
5722 *
5723 * @todo add holes if possible
5724 */
5725static
5727 SCIP* scip, /**< SCIP data structure */
5728 SCIP_CONS* cons, /**< linear constraint */
5729 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5730 int* nfixedvars, /**< pointer to count number of fixed variables */
5731 int* nchgbds, /**< pointer to count the number of bound changes */
5732 int* naddconss /**< pointer to count number of added constraints */
5733 )
5734{
5735 SCIP_CONSHDLRDATA* conshdlrdata;
5736 SCIP_CONSHDLR* conshdlr;
5737 SCIP_CONSDATA* consdata;
5738 SCIP_VAR** infcheckvars;
5739 SCIP_Real* infcheckvals;
5740 SCIP_Real minactinfvars;
5741 SCIP_Real maxactinfvars;
5742 SCIP_Real lb;
5743 SCIP_Real ub;
5744 SCIP_Real feastol;
5745 SCIP_Real fixedact;
5746 SCIP_Real lhs;
5747 SCIP_Real rhs;
5748 SCIP_Real absminbincoef;
5749 SCIP_Longint gcd;
5750 SCIP_Longint gcdtmp;
5751 SCIP_Bool minactinfvarsinvalid;
5752 SCIP_Bool maxactinfvarsinvalid;
5753 SCIP_Bool possiblegcd;
5754 SCIP_Bool gcdisone;
5755 SCIP_Bool addartconss;
5756 int ninfcheckvars;
5757 int nunfixedvars;
5758 int nfixedconsvars;
5759 int ncontvars;
5760 int pos;
5761 int v;
5762
5763 assert(scip != NULL);
5764 assert(cons != NULL);
5765 assert(cutoff != NULL);
5766 assert(nfixedvars != NULL);
5767 assert(nchgbds != NULL);
5768 assert(naddconss != NULL);
5769
5770 /* modifiable constraint can be changed so we do not have all necessary information */
5771 if( SCIPconsIsModifiable(cons) )
5772 return SCIP_OKAY;
5773
5774 consdata = SCIPconsGetData(cons);
5775 assert(consdata != NULL);
5776
5777 /* we already did full ranged row propagation */
5778 if( consdata->rangedrowpropagated == 2 )
5779 return SCIP_OKAY;
5780
5781 /* at least three variables are needed */
5782 if( consdata->nvars < 3 )
5783 return SCIP_OKAY;
5784
5785 /* do nothing on normal inequalities */
5786 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5787 return SCIP_OKAY;
5788
5789 /* get constraint handler data */
5790 conshdlr = SCIPconsGetHdlr(cons);
5791 assert(conshdlr != NULL);
5792 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5793 assert(conshdlrdata != NULL);
5794
5795 addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5796
5797 /* we may add artificial constraints */
5798 if( addartconss )
5799 consdata->rangedrowpropagated = 2;
5800 /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5801 * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5802 * artificial constraints
5803 */
5804 else
5805 {
5806 if( consdata->rangedrowpropagated > 0 )
5807 return SCIP_OKAY;
5808
5809 consdata->rangedrowpropagated = 1;
5810 }
5811 fixedact = 0;
5812 nfixedconsvars = 0;
5813 /* calculate fixed activity and number of fixed variables */
5814 for( v = consdata->nvars - 1; v >= 0; --v )
5815 {
5816 /* all zero coefficients should be eliminated */
5817 assert(!SCIPisZero(scip, consdata->vals[v]));
5818
5819 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5820 {
5821 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5822 ++nfixedconsvars;
5823 }
5824 }
5825
5826 /* do not work with huge fixed activities */
5827 if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5828 return SCIP_OKAY;
5829
5830 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5831 assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5832 lhs = consdata->lhs - fixedact;
5833 rhs = consdata->rhs - fixedact;
5834 nunfixedvars = consdata->nvars - nfixedconsvars;
5835
5836 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5837 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5838 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5839
5840 absminbincoef = SCIP_REAL_MAX;
5841 ncontvars = 0;
5842 gcdisone = TRUE;
5843 possiblegcd = TRUE;
5844
5845 /* we now partition all unfixed variables in two groups:
5846 *
5847 * the first one contains all integral variable with integral
5848 * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5849 * given
5850 *
5851 * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5852 * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5853 */
5854
5855 /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5856 * variables
5857 */
5858 ninfcheckvars = 0;
5859 v = -1;
5860 pos = -1;
5861 do
5862 {
5863 ++v;
5864
5865 /* partition the variables, do not change the order of collection, because it might be used later on */
5866 while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5867 !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5868 {
5869 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5870 {
5871 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5872 {
5873 ++ncontvars;
5874 }
5875 else if( SCIPvarIsBinary(consdata->vars[v]) )
5876 {
5877 SCIP_Real absval;
5878
5879 absval = REALABS(consdata->vals[v]);
5880
5881 if( absminbincoef > absval )
5882 absminbincoef = absval;
5883 }
5884
5885 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5886 possiblegcd = FALSE;
5887 infcheckvars[ninfcheckvars] = consdata->vars[v];
5888 infcheckvals[ninfcheckvars] = consdata->vals[v];
5889 ++ninfcheckvars;
5890
5891 if( pos == -1 )
5892 pos = v;
5893 }
5894 ++v;
5895 }
5896 }
5897 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5898
5899 /* if the first group of variables is empty, we stop */
5900 /* @todo try to propagate/split up a constraint of the form:
5901 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5902 * with k \in Z, c \in (d,d + 1], d \in Z, (a_1*y_1 + ... + a_n*y_n) \in (c-1 + d,d + 1]
5903 */
5904 if( v == consdata->nvars )
5905 goto TERMINATE;
5906
5907 /* we need at least two non-continuous variables */
5908 if( ncontvars + 2 > nunfixedvars )
5909 goto TERMINATE;
5910
5911 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5912 assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
5913
5914 feastol = SCIPfeastol(scip);
5915
5916 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5917 assert(gcd >= 2);
5918
5919 /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5920 * calculate gcd over the first part of variables */
5921 for( ; v < consdata->nvars; ++v )
5922 {
5923 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5924 continue;
5925
5926 if( SCIPvarIsBinary(consdata->vars[v]) )
5927 {
5928 SCIP_Real absval;
5929
5930 absval = REALABS(consdata->vals[v]);
5931
5932 if( absminbincoef > absval )
5933 absminbincoef = absval;
5934 }
5935
5936 if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5937 SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5938 {
5939 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5940 ++ncontvars;
5941
5942 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5943 possiblegcd = FALSE;
5944 infcheckvars[ninfcheckvars] = consdata->vars[v];
5945 infcheckvals[ninfcheckvars] = consdata->vals[v];
5946
5947 ++ninfcheckvars;
5948
5949 if( pos == -1 )
5950 pos = v;
5951 }
5952 else
5953 {
5954 assert(REALABS(consdata->vals[v]) > 1.5);
5955
5956 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5957 assert(gcdtmp >= 1);
5958
5959 if( gcdtmp == 1 )
5960 {
5961 infcheckvars[ninfcheckvars] = consdata->vars[v];
5962 infcheckvals[ninfcheckvars] = consdata->vals[v];
5963
5964 ++ninfcheckvars;
5965
5966 if( pos == -1 )
5967 pos = v;
5968 }
5969 else
5970 gcd = gcdtmp;
5971 }
5972 }
5973 assert(gcd >= 2);
5974
5975 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5976 * normalizeCons() */
5977 if( ninfcheckvars == 0 )
5978 goto TERMINATE;
5979
5980 assert(pos >= 0);
5981
5982 minactinfvarsinvalid = FALSE;
5983 maxactinfvarsinvalid = FALSE;
5984 maxactinfvars = 0.0;
5985 minactinfvars = 0.0;
5986
5987 /* calculate activities over all infcheckvars */
5988 for( v = ninfcheckvars - 1; v >= 0; --v )
5989 {
5990 lb = SCIPvarGetLbLocal(infcheckvars[v]);
5991 ub = SCIPvarGetUbLocal(infcheckvars[v]);
5992
5993 if( SCIPisInfinity(scip, -lb) )
5994 {
5995 if( infcheckvals[v] < 0.0 )
5996 maxactinfvarsinvalid = TRUE;
5997 else
5998 minactinfvarsinvalid = TRUE;
5999 }
6000 else
6001 {
6002 if( infcheckvals[v] < 0.0 )
6003 maxactinfvars += infcheckvals[v] * lb;
6004 else
6005 minactinfvars += infcheckvals[v] * lb;
6006 }
6007
6008 if( SCIPisInfinity(scip, ub) )
6009 {
6010 if( infcheckvals[v] > 0.0 )
6011 maxactinfvarsinvalid = TRUE;
6012 else
6013 minactinfvarsinvalid = TRUE;
6014 }
6015 else
6016 {
6017 if( infcheckvals[v] > 0.0 )
6018 maxactinfvars += infcheckvals[v] * ub;
6019 else
6020 minactinfvars += infcheckvals[v] * ub;
6021 }
6022
6023 /* better abort on to big values */
6024 if( SCIPisHugeValue(scip, -minactinfvars) )
6025 minactinfvarsinvalid = TRUE;
6026 if( SCIPisHugeValue(scip, maxactinfvars) )
6027 maxactinfvarsinvalid = TRUE;
6028
6029 if( minactinfvarsinvalid || maxactinfvarsinvalid )
6030 goto TERMINATE;
6031 }
6032 assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6033
6034 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6035 minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6036
6037 /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6038 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6039 * activities */
6040 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6041 * !!!note!!!
6042 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6043 * are not at their global bound
6044 */
6045
6046 /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6047 * infeasibility */
6048 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6049 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6050 {
6051 SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6053
6054 /* start conflict analysis */
6055 /* @todo improve conflict analysis by adding relaxed bounds */
6056 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6057
6058 *cutoff = TRUE;
6059 }
6060 else if( ncontvars == 0 )
6061 {
6062 SCIP_Longint gcdinfvars = -1;
6063
6064 /* check for gcd over all infcheckvars */
6065 if( possiblegcd )
6066 {
6067 v = ninfcheckvars - 1;
6068 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6069 assert(gcdinfvars >= 2);
6070
6071 for( ; v >= 0 && gcdinfvars >= 2; --v )
6072 {
6073 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6074 }
6075 }
6076 else if( gcdisone )
6077 gcdinfvars = 1;
6078
6079 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6080
6081 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6082 if( gcdinfvars >= 1 )
6083 {
6084 SCIP_Real value;
6085 SCIP_Real value2;
6086 SCIP_Real minvalue = SCIP_INVALID;
6087 SCIP_Real maxvalue = SCIP_INVALID;
6088 int nsols = 0;
6089
6090 value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6091
6092 /* check how many possible solutions exist */
6093 while( SCIPisLE(scip, value, maxactinfvars) )
6094 {
6095 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6096
6097 /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6098 if( !SCIPisGE(scip, value2, lhs) )
6099 {
6100 value2 += gcd;
6101 }
6102
6103 if( SCIPisLE(scip, value2, rhs) )
6104 {
6105 ++nsols;
6106
6107 /* early termination if we found more than two solutions */
6108 if( nsols == 3 )
6109 break;
6110
6111 if( minvalue == SCIP_INVALID ) /*lint !e777*/
6112 minvalue = value;
6113
6114 maxvalue = value;
6115 }
6116 value += gcdinfvars;
6117 }
6118 assert(nsols < 2 || minvalue <= maxvalue);
6119
6120 /* determine last possible solution for better bounding */
6121 if( nsols == 3 )
6122 {
6123#ifndef NDEBUG
6124 SCIP_Real secondsolval = maxvalue;
6125#endif
6126 value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6127
6128 /* check how many possible solutions exist */
6129 while( SCIPisGE(scip, value, minactinfvars) )
6130 {
6131 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6132
6133 /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6134 if( !SCIPisLE(scip, value2, rhs) )
6135 {
6136 value2 -= gcd;
6137 }
6138
6139 if( SCIPisGE(scip, value2, lhs) )
6140 {
6141 maxvalue = value;
6142 assert(maxvalue > minvalue);
6143 break;
6144 }
6145 value -= gcdinfvars;
6146 }
6147 assert(maxvalue > secondsolval);
6148 }
6149
6150 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6151 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6152
6153 /* no possible solution found */
6154 if( nsols == 0 )
6155 {
6156 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6157 gcdinfvars, gcd, lhs, rhs);
6158 SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6160
6161 /* start conflict analysis */
6162 /* @todo improve conflict analysis by adding relaxed bounds */
6163 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6164
6165 *cutoff = TRUE;
6166 }
6167 /* if only one solution exist we can extract a new constraint or fix variables */
6168 else if( nsols == 1 )
6169 {
6170 assert(minvalue == maxvalue); /*lint !e777*/
6171
6172 /* we can fix the only variable in our second set of variables */
6173 if( ninfcheckvars == 1 )
6174 {
6175 SCIP_Bool fixed;
6176
6177 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6178
6179 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6180 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6181 SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6182
6183 /* fix variable to only possible value */
6184 SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6185 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6186
6187 if( *cutoff )
6188 {
6189 /* start conflict analysis */
6190 /* @todo improve conflict analysis by adding relaxed bounds */
6191 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6192 }
6193
6194 if( fixed )
6195 ++(*nfixedvars);
6196 }
6197 else
6198 {
6199 /* check for exactly one unfixed variable which is not part of the infcheckvars */
6200 if( ninfcheckvars == nunfixedvars - 1 )
6201 {
6203 SCIP_Bool foundvar = FALSE;
6204 SCIP_Bool fixed;
6205 int w = 0;
6206
6207 assert(ninfcheckvars > 0);
6208
6209 /* find variable which is not an infcheckvar and fix it */
6210 for( v = 0; v < consdata->nvars - 1; ++v )
6211 {
6212 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6213 {
6214 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6215 {
6216#ifndef NDEBUG
6217 int v2 = v + 1;
6218 int w2 = w;
6219
6220 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6221
6222 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6223 {
6224 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6225 continue;
6226
6227 assert(consdata->vars[v2] == infcheckvars[w2]);
6228 ++w2;
6229 }
6230 assert(w2 == ninfcheckvars);
6231#endif
6232 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6233
6234 foundvar = TRUE;
6235
6236 if( consdata->vals[v] < 0 )
6237 {
6238 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6239 }
6240 else
6241 {
6242 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6243 }
6244
6245 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6246 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6247 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6248
6249 /* fix variable to only possible value */
6250 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6251 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6252
6253 if( *cutoff )
6254 {
6255 /* start conflict analysis */
6256 /* @todo improve conflict analysis by adding relaxed bounds */
6257 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6258 consdata->vars[v], bound) );
6259 }
6260
6261 if( fixed )
6262 ++(*nfixedvars);
6263
6264 break;
6265 }
6266
6267 ++w;
6268 }
6269 }
6270
6271 /* maybe last variable was the not infcheckvar */
6272 if( !foundvar )
6273 {
6274 assert(v == consdata->nvars - 1);
6275 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6276
6277 if( consdata->vals[v] < 0 )
6278 {
6279 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6280 }
6281 else
6282 {
6283 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6284 }
6285
6286 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6287 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6288 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6289
6290 /* fix variable to only possible value */
6291 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6292 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6293
6294 if( *cutoff )
6295 {
6296 /* start conflict analysis */
6297 /* @todo improve conflict analysis by adding relaxed bounds */
6298 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6299 consdata->vars[v], bound) );
6300 }
6301
6302 if( fixed )
6303 ++(*nfixedvars);
6304 }
6305 }
6306 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6307 {
6308 /* aggregation possible if we have two variables, but this will be done later on */
6309 SCIP_CONS* newcons;
6310 char name[SCIP_MAXSTRLEN];
6311
6312 /* create, add, and release new artificial constraint */
6313 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6314 ++conshdlrdata->naddconss;
6315
6316 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6317
6318 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6319 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6320 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6321
6322 SCIPdebugPrintCons(scip, newcons, NULL);
6323
6324 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6325
6326 ++(*naddconss);
6327 }
6328 }
6329 }
6330 /* at least two solutions */
6331 else
6332 {
6333 /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6334
6335 /* only one variable in the second set, so we can bound this variables */
6336 if( ninfcheckvars == 1 )
6337 {
6338 SCIP_Bool tightened;
6339 SCIP_Real newlb;
6340 SCIP_Real newub;
6341
6342 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6343
6344 if( infcheckvals[0] < 0 )
6345 {
6346 newlb = maxvalue/infcheckvals[0];
6347 newub = minvalue/infcheckvals[0];
6348 }
6349 else
6350 {
6351 newlb = minvalue/infcheckvals[0];
6352 newub = maxvalue/infcheckvals[0];
6353 }
6354 assert(newlb < newub);
6355
6356 if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6357 {
6358 /* update lower bound of variable */
6359 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6360 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6361
6362 /* tighten variable lower bound to minimal possible value */
6363 SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6364 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6365
6366 if( *cutoff )
6367 {
6368 /* start conflict analysis */
6369 /* @todo improve conflict analysis by adding relaxed bounds */
6370 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6371 }
6372
6373 if( tightened )
6374 ++(*nchgbds);
6375 }
6376
6377 if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6378 {
6379 /* update upper bound of variable */
6380 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6381 SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6382
6383 /* tighten variable upper bound to maximal possible value */
6384 SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6385 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6386
6387 if( *cutoff )
6388 {
6389 /* start conflict analysis */
6390 /* @todo improve conflict analysis by adding relaxed bounds */
6391 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6392 }
6393
6394 if( tightened )
6395 ++(*nchgbds);
6396 }
6397 }
6398 /* check if we have only one not infcheckvars, if so we can tighten this variable */
6399 else if( ninfcheckvars == nunfixedvars - 1 )
6400 {
6401 SCIP_Bool foundvar = FALSE;
6402 SCIP_Bool tightened;
6403 SCIP_Real newlb;
6404 SCIP_Real newub;
6405 int w = 0;
6406
6407 assert(ninfcheckvars > 0);
6408 assert(minvalue < maxvalue);
6409
6410 /* find variable which is not an infcheckvar and fix it */
6411 for( v = 0; v < consdata->nvars - 1; ++v )
6412 {
6413 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6414 {
6415 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6416 {
6417#ifndef NDEBUG
6418 int v2 = v + 1;
6419 int w2 = w;
6420
6421 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6422
6423 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6424 {
6425 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6426 continue;
6427
6428 assert(consdata->vars[v2] == infcheckvars[w2]);
6429 ++w2;
6430 }
6431 assert(w2 == ninfcheckvars);
6432#endif
6433
6434 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6435 foundvar = TRUE;
6436
6437 if( consdata->vals[v] < 0 )
6438 {
6439 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6440 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6441 }
6442 else
6443 {
6444 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6445 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6446 }
6447 assert(SCIPisLE(scip, newlb, newub));
6448
6449 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6450 {
6451 /* update lower bound of variable */
6452 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6453 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6454
6455 /* tighten variable lower bound to minimal possible value */
6456 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6457 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6458
6459 if( *cutoff )
6460 {
6461 /* start conflict analysis */
6462 /* @todo improve conflict analysis by adding relaxed bounds */
6463 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6464 consdata->vars[v], newlb) );
6465 }
6466
6467 if( tightened )
6468 ++(*nchgbds);
6469 }
6470
6471 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6472 {
6473 /* update upper bound of variable */
6474 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6475 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6476
6477 /* tighten variable upper bound to maximal possible value */
6478 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6479 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6480
6481 if( *cutoff )
6482 {
6483 /* start conflict analysis */
6484 /* @todo improve conflict analysis by adding relaxed bounds */
6485 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6486 consdata->vars[v], newub) );
6487 }
6488
6489 if( tightened )
6490 ++(*nchgbds);
6491 }
6492
6493 break;
6494 }
6495
6496 ++w;
6497 }
6498 }
6499
6500 /* maybe last variable was the not infcheckvar */
6501 if( !foundvar )
6502 {
6503 assert(v == consdata->nvars - 1);
6504 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6505
6506 if( consdata->vals[v] < 0 )
6507 {
6508 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6509 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6510 }
6511 else
6512 {
6513 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6514 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6515 }
6516 assert(SCIPisLE(scip, newlb, newub));
6517
6518 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6519 {
6520 /* update lower bound of variable */
6521 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6522 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6523
6524 /* tighten variable lower bound to minimal possible value */
6525 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6526 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6527
6528 if( *cutoff )
6529 {
6530 /* start conflict analysis */
6531 /* @todo improve conflict analysis by adding relaxed bounds */
6532 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6533 }
6534
6535 if( tightened )
6536 ++(*nchgbds);
6537 }
6538
6539 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6540 {
6541 /* update upper bound of variable */
6542 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6543 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6544
6545 /* tighten variable upper bound to maximal possible value */
6546 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6547 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6548
6549 if( *cutoff )
6550 {
6551 /* start conflict analysis */
6552 /* @todo improve conflict analysis by adding relaxed bounds */
6553 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6554 }
6555
6556 if( tightened )
6557 ++(*nchgbds);
6558 }
6559 }
6560 }
6561 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6562 * region for our infcheckvars, if possible
6563 */
6564 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6565 {
6566 SCIP_CONS* newcons;
6567 char name[SCIP_MAXSTRLEN];
6568 SCIP_Real newlhs;
6569 SCIP_Real newrhs;
6570
6571 assert(maxvalue > minvalue);
6572
6573 if( SCIPisGT(scip, minvalue, minactinfvars) )
6574 newlhs = minvalue;
6575 else
6576 newlhs = -SCIPinfinity(scip);
6577
6578 if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6579 newrhs = maxvalue;
6580 else
6581 newrhs = SCIPinfinity(scip);
6582
6583 if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6584 {
6585 /* create, add, and release new artificial constraint */
6586 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6587 ++conshdlrdata->naddconss;
6588
6589 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6590
6591 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6593 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6594
6595 SCIPdebugPrintCons(scip, newcons, NULL);
6596 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6597
6598 ++(*naddconss);
6599 }
6600 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6601 * should be maxvalue */
6602 }
6603 }
6604 }
6605 }
6606 else if( addartconss && ncontvars < ninfcheckvars )
6607 {
6608 SCIP_Real maxact = 0.0;
6609 SCIP_Real minact = 0.0;
6610 int w = 0;
6611
6612 /* compute activities of non-infcheckvars */
6613 for( v = 0; v < consdata->nvars; ++v )
6614 {
6615 if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6616 {
6617 ++w;
6618 continue;
6619 }
6620
6621 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6622 {
6623 if( SCIPvarIsBinary(consdata->vars[v]) )
6624 {
6625 if( consdata->vals[v] > 0.0 )
6626 maxact += consdata->vals[v];
6627 else
6628 minact += consdata->vals[v];
6629 }
6630 else
6631 {
6632 SCIP_Real tmpval;
6633
6634 assert(SCIPvarIsIntegral(consdata->vars[v]));
6635
6636 if( consdata->vals[v] > 0.0 )
6637 {
6638 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6639
6640 if( SCIPisHugeValue(scip, -tmpval) )
6641 break;
6642
6643 minact += tmpval;
6644
6645 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6646
6647 if( SCIPisHugeValue(scip, tmpval) )
6648 break;
6649
6650 maxact += tmpval;
6651 }
6652 else
6653 {
6654 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6655
6656 if( SCIPisHugeValue(scip, -tmpval) )
6657 break;
6658
6659 minact += tmpval;
6660
6661 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6662
6663 if( SCIPisHugeValue(scip, tmpval) )
6664 break;
6665
6666 maxact += tmpval;
6667 }
6668 }
6669 }
6670 }
6671 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6672 {
6673 SCIP_CONS* newcons;
6674 char name[SCIP_MAXSTRLEN];
6675 SCIP_Real newlhs;
6676 SCIP_Real newrhs;
6677
6678 assert(maxact > minact);
6679 assert(w == ninfcheckvars);
6680
6681 newlhs = lhs - maxact;
6682 newrhs = rhs - minact;
6683 assert(newlhs < newrhs);
6684
6685 /* create, add, and release new artificial constraint */
6686 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6687 ++conshdlrdata->naddconss;
6688
6689 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6690
6691 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6693 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6694
6695 SCIPdebugPrintCons(scip, newcons, NULL);
6696 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6697
6698 ++(*naddconss);
6699 }
6700 }
6701
6702 TERMINATE:
6703 SCIPfreeBufferArray(scip, &infcheckvals);
6704 SCIPfreeBufferArray(scip, &infcheckvars);
6705
6706 return SCIP_OKAY;
6707}
6708
6709/** tightens bounds of a single variable due to activity bounds */
6710static
6712 SCIP* scip, /**< SCIP data structure */
6713 SCIP_CONS* cons, /**< linear constraint */
6714 int pos, /**< position of the variable in the vars array */
6715 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6716 int* nchgbds, /**< pointer to count the total number of tightened bounds */
6717 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6718 )
6719{
6720 SCIP_CONSDATA* consdata;
6721 SCIP_VAR* var;
6722 SCIP_Real val;
6723 SCIP_Real lb;
6724 SCIP_Real ub;
6725 SCIP_Real minresactivity;
6726 SCIP_Real maxresactivity;
6727 SCIP_Real lhs;
6728 SCIP_Real rhs;
6729 SCIP_Bool infeasible;
6730 SCIP_Bool tightened;
6731 SCIP_Bool ismintight;
6732 SCIP_Bool ismaxtight;
6733 SCIP_Bool isminsettoinfinity;
6734 SCIP_Bool ismaxsettoinfinity;
6735
6736 assert(scip != NULL);
6737 assert(cons != NULL);
6738 assert(cutoff != NULL);
6739 assert(nchgbds != NULL);
6740
6741 /* we cannot tighten variables' bounds, if the constraint may be not complete */
6742 if( SCIPconsIsModifiable(cons) )
6743 return SCIP_OKAY;
6744
6745 consdata = SCIPconsGetData(cons);
6746 assert(consdata != NULL);
6747 assert(0 <= pos && pos < consdata->nvars);
6748
6749 *cutoff = FALSE;
6750
6751 var = consdata->vars[pos];
6752
6753 /* we cannot tighten bounds of multi-aggregated variables */
6755 return SCIP_OKAY;
6756
6757 val = consdata->vals[pos];
6758 lhs = consdata->lhs;
6759 rhs = consdata->rhs;
6760 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6761 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
6762 assert(var != NULL);
6763 assert(!SCIPisZero(scip, val));
6764 assert(!SCIPisInfinity(scip, lhs));
6765 assert(!SCIPisInfinity(scip, -rhs));
6766
6767 lb = SCIPvarGetLbLocal(var);
6768 ub = SCIPvarGetUbLocal(var);
6769 assert(SCIPisLE(scip, lb, ub));
6770
6771 if( val > 0.0 )
6772 {
6773 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6774 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6775 */
6776 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6777 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6778 {
6779 SCIP_Real newub;
6780
6781 newub = (rhs - minresactivity)/val;
6782
6783 if( !SCIPisInfinity(scip, newub) &&
6784 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6785 {
6786 SCIP_Bool activityunreliable;
6787 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6788
6789 /* check minresactivities for reliability */
6790 if( activityunreliable )
6791 {
6792 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6793 newub = (rhs - minresactivity)/val;
6794 activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6795 (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6796 && (!force || !SCIPisLT(scip, newub, ub)));
6797 }
6798
6799 if( !activityunreliable )
6800 {
6801 /* tighten upper bound */
6802 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6803 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6804 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6805 &infeasible, &tightened) );
6806 if( infeasible )
6807 {
6808 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6809 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6810
6811 /* analyze conflict */
6813
6814 *cutoff = TRUE;
6815 return SCIP_OKAY;
6816 }
6817 if( tightened )
6818 {
6819 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6820 assert(SCIPisFeasLE(scip, ub, newub));
6821 (*nchgbds)++;
6822
6823 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6824 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6825 }
6826 }
6827 }
6828 }
6829
6830 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6831 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6832 {
6833 SCIP_Real newlb;
6834
6835 newlb = (lhs - maxresactivity)/val;
6836 if( !SCIPisInfinity(scip, -newlb) &&
6837 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6838 {
6839 /* check maxresactivities for reliability */
6840 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6841 {
6842 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6843 newlb = (lhs - maxresactivity)/val;
6844
6845 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6846 && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6847 && (!force || !SCIPisGT(scip, newlb, lb))) )
6848 return SCIP_OKAY;
6849 }
6850
6851 /* tighten lower bound */
6852 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6853 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6854 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6855 &infeasible, &tightened) );
6856 if( infeasible )
6857 {
6858 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6859 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6860
6861 /* analyze conflict */
6863
6864 *cutoff = TRUE;
6865 return SCIP_OKAY;
6866 }
6867 if( tightened )
6868 {
6869 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6870 assert(SCIPisFeasGE(scip, lb, newlb));
6871 (*nchgbds)++;
6872 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6873 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6874 }
6875 }
6876 }
6877 }
6878 else
6879 {
6880 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6881 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6882 */
6883 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6884 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6885 {
6886 SCIP_Real newlb;
6887
6888 newlb = (rhs - minresactivity)/val;
6889 if( !SCIPisInfinity(scip, -newlb) &&
6890 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6891 {
6892 SCIP_Bool activityunreliable;
6893 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6894 /* check minresactivities for reliability */
6895 if( activityunreliable )
6896 {
6897 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6898 newlb = (rhs - minresactivity)/val;
6899
6900 activityunreliable = SCIPisInfinity(scip, -minresactivity)
6901 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6902 && (!force || !SCIPisGT(scip, newlb, lb)));
6903 }
6904
6905 if( !activityunreliable )
6906 {
6907 /* tighten lower bound */
6908 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6909 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6910 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6911 &infeasible, &tightened) );
6912 if( infeasible )
6913 {
6914 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6915 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6916
6917 /* analyze conflict */
6919
6920 *cutoff = TRUE;
6921 return SCIP_OKAY;
6922 }
6923 if( tightened )
6924 {
6925 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6926 assert(SCIPisFeasGE(scip, lb, newlb));
6927 (*nchgbds)++;
6928 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6929 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6930 }
6931 }
6932 }
6933 }
6934
6935 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6936 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6937 {
6938 SCIP_Real newub;
6939
6940 newub = (lhs - maxresactivity)/val;
6941 if( !SCIPisInfinity(scip, newub) &&
6942 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6943 {
6944 /* check maxresactivities for reliability */
6945 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6946 {
6947 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6948 newub = (lhs - maxresactivity)/val;
6949
6950 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6951 && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6952 && (!force || !SCIPisLT(scip, newub, ub))) )
6953 return SCIP_OKAY;
6954 }
6955
6956 /* tighten upper bound */
6957 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6958 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6959 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6960 &infeasible, &tightened) );
6961 if( infeasible )
6962 {
6963 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6964 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6965
6966 /* analyze conflict */
6968
6969 *cutoff = TRUE;
6970 return SCIP_OKAY;
6971 }
6972 if( tightened )
6973 {
6974 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6975 assert(SCIPisFeasLE(scip, ub, newub));
6976 (*nchgbds)++;
6977 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6978 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6979 }
6980 }
6981 }
6982 }
6983
6984 return SCIP_OKAY;
6985}
6986
6987#define MAXTIGHTENROUNDS 10
6988
6989/** tightens bounds of variables in constraint due to activity bounds */
6990static
6992 SCIP* scip, /**< SCIP data structure */
6993 SCIP_CONS* cons, /**< linear constraint */
6994 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
6995 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6996 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6997 int* nchgbds /**< pointer to count the total number of tightened bounds */
6998 )
6999{
7000 SCIP_CONSDATA* consdata;
7001 unsigned int tightenmode;
7002 int nvars;
7003 int nrounds;
7004 int lastchange;
7005 int oldnchgbds;
7006#ifndef SCIP_DEBUG
7007 int oldnchgbdstotal;
7008#endif
7009 int v;
7010 SCIP_Bool force;
7011 SCIP_Bool easycase;
7012
7013 assert(scip != NULL);
7014 assert(cons != NULL);
7015 assert(nchgbds != NULL);
7016 assert(cutoff != NULL);
7017
7018 *cutoff = FALSE;
7019
7020 /* we cannot tighten variables' bounds, if the constraint may be not complete */
7021 if( SCIPconsIsModifiable(cons) )
7022 return SCIP_OKAY;
7023
7024 /* if a constraint was created after presolve, then it may hold fixed variables
7025 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7026 * thus, ensure here again that variable fixings have been applied
7027 */
7028 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7029 if( *cutoff )
7030 return SCIP_OKAY;
7031
7032 /* check if constraint has any chances of tightening bounds */
7033 if( !canTightenBounds(cons) )
7034 return SCIP_OKAY;
7035
7036 consdata = SCIPconsGetData(cons);
7037 assert(consdata != NULL);
7038
7039 nvars = consdata->nvars;
7040 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7041
7042 /* we are at the root node or during presolving */
7043 if( SCIPgetDepth(scip) < 1 )
7044 tightenmode = 2;
7045 else
7046 tightenmode = 1;
7047
7048 /* stop if we already tightened the constraint and the tightening is not forced */
7049 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7050 return SCIP_OKAY;
7051
7052 /* ensure that the variables are properly sorted */
7053 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7054 {
7055 SCIP_CALL( consdataSort(scip, consdata) );
7056 assert(consdata->coefsorted);
7057 }
7058
7059 /* update maximal activity delta if necessary */
7060 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7062
7063 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7064 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7065 checkMaxActivityDelta(scip, consdata);
7066
7067 /* this may happen if all variables are fixed */
7068 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7069 return SCIP_OKAY;
7070
7071 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7072 {
7073 SCIP_Real slack;
7074 SCIP_Real surplus;
7075 SCIP_Real minactivity;
7076 SCIP_Real maxactivity;
7077 SCIP_Bool ismintight;
7078 SCIP_Bool ismaxtight;
7079 SCIP_Bool isminsettoinfinity;
7080 SCIP_Bool ismaxsettoinfinity;
7081
7082 /* use maximal activity delta to skip propagation (cannot deduce anything) */
7083 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &ismintight, &ismaxtight,
7084 &isminsettoinfinity, &ismaxsettoinfinity);
7085 assert(!SCIPisInfinity(scip, minactivity));
7086 assert(!SCIPisInfinity(scip, -maxactivity));
7087
7088 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7089 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7090
7091 /* check if the constraint will propagate */
7092 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7093 return SCIP_OKAY;
7094 }
7095
7096 /* check if we can use fast implementation for easy and numerically well behaved cases */
7097 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7098
7099 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7100 lastchange = -1;
7101 oldnchgbds = 0;
7102
7103#ifndef SCIP_DEBUG
7104 oldnchgbdstotal = *nchgbds;
7105#endif
7106
7107 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7108 {
7109 /* ensure that the variables are properly sorted
7110 *
7111 * note: it might happen that integer variables become binary during bound tightening at the root node
7112 */
7113 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7114 {
7115 SCIP_CALL( consdataSort(scip, consdata) );
7116 assert(consdata->coefsorted);
7117 }
7118
7119 /* mark the constraint to have the variables' bounds tightened */
7120 consdata->boundstightened = (unsigned int)tightenmode;
7121
7122 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7123 * sorting enables skipping variables
7124 */
7125 v = 0;
7126 while( v < nvars && v != lastchange && !(*cutoff) )
7127 {
7128 oldnchgbds = *nchgbds;
7129
7130 if( easycase )
7131 {
7132 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7133 }
7134 else
7135 {
7136 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7137 }
7138
7139 /* if there was no progress, skip the rest of the binary variables */
7140 if( *nchgbds > oldnchgbds )
7141 {
7142 lastchange = v;
7143 ++v;
7144 }
7145 else if( consdata->coefsorted && v < consdata->nbinvars - 1
7146 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7147 v = consdata->nbinvars;
7148 else
7149 ++v;
7150 }
7151
7152#ifndef SCIP_DEBUG
7153 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7154 *nchgbds - oldnchgbdstotal, nrounds);
7155 oldnchgbdstotal += oldnchgbds;
7156#endif
7157 }
7158
7159#ifndef NDEBUG
7160 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7161 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7162#endif
7163
7164 return SCIP_OKAY;
7165}
7166
7167/** checks linear constraint for feasibility of given solution or current solution */
7168static
7170 SCIP* scip, /**< SCIP data structure */
7171 SCIP_CONS* cons, /**< linear constraint */
7172 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7173 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7174 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7175 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7176 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7177 )
7178{
7179 SCIP_CONSDATA* consdata;
7180 SCIP_Real activity;
7181 SCIP_Real absviol;
7182 SCIP_Real relviol;
7183 SCIP_Real lhsviol;
7184 SCIP_Real rhsviol;
7185
7186 assert(scip != NULL);
7187 assert(cons != NULL);
7188 assert(violated != NULL);
7189
7190 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7192
7193 consdata = SCIPconsGetData(cons);
7194 assert(consdata != NULL);
7195
7196 *violated = FALSE;
7197
7198 if( consdata->row != NULL )
7199 {
7200 if( !checklprows && SCIProwIsInLP(consdata->row) )
7201 return SCIP_OKAY;
7202 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7203 activity = consdataComputePseudoActivity(scip, consdata);
7204 else
7205 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7206 }
7207 else
7208 activity = consdataGetActivity(scip, consdata, sol);
7209
7210 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7211 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7212 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7213 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7214
7215 /* calculate absolute and relative bound violations */
7216 lhsviol = consdata->lhs - activity;
7217 rhsviol = activity - consdata->rhs;
7218
7219 absviol = 0.0;
7220 relviol = 0.0;
7221 if( (lhsviol > 0) && (lhsviol > rhsviol) )
7222 {
7223 absviol = lhsviol;
7224 relviol = SCIPrelDiff(consdata->lhs, activity);
7225 }
7226 else if( rhsviol > 0 )
7227 {
7228 absviol = rhsviol;
7229 relviol = SCIPrelDiff(activity, consdata->rhs);
7230 }
7231
7232 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7233 * return infeasible for safety
7234 */
7235 if( activity == SCIP_INVALID ) /*lint !e777*/
7236 {
7237 assert(sol == NULL);
7238 *violated = TRUE;
7239
7240 /* set violation of invalid pseudo solutions */
7241 absviol = SCIP_INVALID;
7242 relviol = SCIP_INVALID;
7243
7244 /* reset constraint age since we are in enforcement */
7246 }
7247 /* check with relative tolerances (the default) */
7248 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7249 {
7250 /* the "normal" check: one of the two sides is violated */
7251 if( !checkrelmaxabs )
7252 {
7253 *violated = TRUE;
7254
7255 /* only reset constraint age if we are in enforcement */
7256 if( sol == NULL )
7257 {
7259 }
7260 }
7261 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7262 * small compared to the absolute values occurring in the activity
7263 */
7264 else
7265 {
7266 SCIP_Real maxabs;
7267 SCIP_Real coef;
7268 SCIP_Real absval;
7269 SCIP_Real solval;
7270 int v;
7271
7272 maxabs = 1.0;
7273
7274 /* compute maximum absolute value */
7275 for( v = 0; v < consdata->nvars; ++v )
7276 {
7277 if( consdata->vals != NULL )
7278 {
7279 coef = consdata->vals[v];
7280 }
7281 else
7282 coef = 1.0;
7283
7284 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7285 absval = REALABS( coef * solval );
7286 maxabs = MAX( maxabs, absval );
7287 }
7288
7289 /* regard left hand side, first */
7290 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7291 {
7292 /* check whether violation is random noise */
7293 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7294 {
7295 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7296 consdata->lhs - activity, maxabs);
7297 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7298
7299 /* only increase constraint age if we are in enforcement */
7300 if( sol == NULL )
7301 {
7302 SCIP_CALL( SCIPincConsAge(scip, cons) );
7303 }
7304 }
7305 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7306 else if( SCIPisZero(scip, consdata->lhs) )
7307 {
7308 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7309 {
7310 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7311 consdata->lhs - activity, maxabs);
7312 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7313
7314 /* only increase constraint age if we are in enforcement */
7315 if( sol == NULL )
7316 {
7317 SCIP_CALL( SCIPincConsAge(scip, cons) );
7318 }
7319 }
7320 else
7321 {
7322 *violated = TRUE;
7323
7324 /* only reset constraint age if we are in enforcement */
7325 if( sol == NULL )
7326 {
7328 }
7329 }
7330 }
7331 else
7332 {
7333 *violated = TRUE;
7334
7335 /* only reset constraint age if we are in enforcement */
7336 if( sol == NULL )
7337 {
7339 }
7340 }
7341 }
7342
7343 /* now regard right hand side */
7344 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7345 {
7346 /* check whether violation is random noise */
7347 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7348 {
7349 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7350 activity - consdata->rhs, maxabs);
7351 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7352
7353 /* only increase constraint age if we are in enforcement */
7354 if( sol == NULL )
7355 {
7356 SCIP_CALL( SCIPincConsAge(scip, cons) );
7357 }
7358 }
7359 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7360 else if( SCIPisZero(scip, consdata->rhs) )
7361 {
7362 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7363 {
7364 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7365 activity - consdata->rhs, maxabs);
7366 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7367
7368 /* only increase constraint age if we are in enforcement */
7369 if( sol == NULL )
7370 {
7371 SCIP_CALL( SCIPincConsAge(scip, cons) );
7372 }
7373 }
7374 else
7375 {
7376 *violated = TRUE;
7377
7378 /* only reset constraint age if we are in enforcement */
7379 if( sol == NULL )
7380 {
7382 }
7383 }
7384 }
7385 else
7386 {
7387 *violated = TRUE;
7388
7389 /* only reset constraint age if we are in enforcement */
7390 if( sol == NULL )
7391 {
7393 }
7394 }
7395 }
7396 }
7397 }
7398 /* check with absolute tolerances */
7399 else if( consdata->checkabsolute &&
7400 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7401 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7402 {
7403 *violated = TRUE;
7404
7405 /* only reset constraint age if we are in enforcement */
7406 if( sol == NULL )
7407 {
7409 }
7410 }
7411 else
7412 {
7413 /* only increase constraint age if we are in enforcement */
7414 if( sol == NULL )
7415 {
7416 SCIP_CALL( SCIPincConsAge(scip, cons) );
7417 }
7418 }
7419
7420 /* update absolute and relative violation of the solution */
7421 if( sol != NULL )
7422 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7423
7424 return SCIP_OKAY;
7425}
7426
7427/** creates an LP row in a linear constraint data */
7428static
7430 SCIP* scip, /**< SCIP data structure */
7431 SCIP_CONS* cons /**< linear constraint */
7432 )
7433{
7434 SCIP_CONSDATA* consdata;
7435
7436 assert(scip != NULL);
7437 assert(cons != NULL);
7438
7439 consdata = SCIPconsGetData(cons);
7440 assert(consdata != NULL);
7441 assert(consdata->row == NULL);
7442
7443 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7445
7446 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7447
7448 return SCIP_OKAY;
7449}
7450
7451/** adds linear constraint as cut to the LP */
7452static
7454 SCIP* scip, /**< SCIP data structure */
7455 SCIP_CONS* cons, /**< linear constraint */
7456 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7457 )
7458{
7459 SCIP_CONSDATA* consdata;
7460
7461 assert(scip != NULL);
7462 assert(cons != NULL);
7463
7464 consdata = SCIPconsGetData(cons);
7465 assert(consdata != NULL);
7466
7467 if( consdata->row == NULL )
7468 {
7469 if( !SCIPconsIsModifiable(cons) )
7470 {
7471 /* replace all fixed variables by active counterparts, as we have no chance to do this anymore after the row has been added to the LP
7472 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7473 */
7474 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7475 if( *cutoff )
7476 return SCIP_OKAY;
7477 }
7478
7479 /* convert consdata object into LP row */
7480 SCIP_CALL( createRow(scip, cons) );
7481 }
7482 assert(consdata->row != NULL);
7483
7484 if( consdata->nvars == 0 )
7485 {
7486 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7487 }
7488
7489 /* insert LP row as cut */
7490 if( !SCIProwIsInLP(consdata->row) )
7491 {
7492 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7493 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7494 /* if presolving is turned off, the row might be trivial */
7495 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7496 {
7497 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7498 }
7499#ifndef NDEBUG
7500 else
7501 {
7502 int pr;
7503 int cr;
7504 SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7505 SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7506 assert( pr == 0 || cr == 0 );
7507 }
7508#endif
7509 }
7510
7511 return SCIP_OKAY;
7512}
7513
7514/** adds linear constraint as row to the NLP, if not added yet */
7515static
7517 SCIP* scip, /**< SCIP data structure */
7518 SCIP_CONS* cons /**< linear constraint */
7519 )
7520{
7521 SCIP_CONSDATA* consdata;
7522
7523 assert(SCIPisNLPConstructed(scip));
7524
7525 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7526 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7527 return SCIP_OKAY;
7528
7529 consdata = SCIPconsGetData(cons);
7530 assert(consdata != NULL);
7531
7532 if( consdata->nlrow == NULL )
7533 {
7534 assert(consdata->lhs <= consdata->rhs);
7535
7536 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7537 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7538
7539 assert(consdata->nlrow != NULL);
7540 }
7541
7542 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7543 {
7544 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7545 }
7546
7547 return SCIP_OKAY;
7548}
7549
7550/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7551static
7553 SCIP* scip, /**< SCIP data structure */
7554 SCIP_CONS* cons, /**< linear constraint */
7555 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7556 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7557 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7558 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7559 * the ones with non-zero dual value? */
7560 int* ncuts, /**< pointer to add up the number of found cuts */
7561 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7562 )
7563{
7564 SCIP_CONSDATA* consdata;
7565 SCIP_Bool violated;
7566 int oldncuts;
7567
7568 assert(scip != NULL);
7569 assert(conshdlrdata != NULL);
7570 assert(cons != NULL);
7571 assert(cutoff != NULL);
7572
7573 consdata = SCIPconsGetData(cons);
7574 assert(ncuts != NULL);
7575 assert(consdata != NULL);
7576
7577 oldncuts = *ncuts;
7578 *cutoff = FALSE;
7579
7580 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7581
7582 if( violated )
7583 {
7584 /* insert LP row as cut */
7585 SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7586 (*ncuts)++;
7587 }
7588 else if( !SCIPconsIsModifiable(cons) && separatecards )
7589 {
7590 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7591 if( !separateall && sol == NULL )
7592 {
7593 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7594 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7595 {
7596 SCIP_Real dualsol;
7597
7598 dualsol = SCIProwGetDualsol(consdata->row);
7599 if( SCIPisFeasNegative(scip, dualsol) )
7600 {
7601 if( !SCIPisInfinity(scip, consdata->rhs) )
7602 {
7603 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7604 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7605 }
7606 }
7607 else if( SCIPisFeasPositive(scip, dualsol) )
7608 {
7609 if( !SCIPisInfinity(scip, -consdata->lhs) )
7610 {
7611 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7612 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7613 }
7614 }
7615 }
7616 }
7617 else
7618 {
7619 if( !SCIPisInfinity(scip, consdata->rhs) )
7620 {
7621 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7622 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7623 }
7624 if( !SCIPisInfinity(scip, -consdata->lhs) )
7625 {
7626 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7627 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7628 }
7629 }
7630 }
7631
7632 if( *ncuts > oldncuts )
7633 {
7635 }
7636
7637 return SCIP_OKAY;
7638}
7639
7640/** propagation method for linear constraints */
7641static
7643 SCIP* scip, /**< SCIP data structure */
7644 SCIP_CONS* cons, /**< linear constraint */
7645 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7646 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7647 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7648 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7649 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7650 int* nchgbds /**< pointer to count the total number of tightened bounds */
7651 )
7652{
7653 SCIP_CONSDATA* consdata;
7654 SCIP_Real minactivity;
7655 SCIP_Real maxactivity;
7656 SCIP_Bool isminacttight;
7657 SCIP_Bool ismaxacttight;
7658 SCIP_Bool isminsettoinfinity;
7659 SCIP_Bool ismaxsettoinfinity;
7660
7661 assert(scip != NULL);
7662 assert(cons != NULL);
7663 assert(cutoff != NULL);
7664 assert(nchgbds != NULL);
7665
7666 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7667
7668 consdata = SCIPconsGetData(cons);
7669 assert(consdata != NULL);
7670
7671 if( consdata->eventdata == NULL )
7672 {
7673 SCIP_CONSHDLR* conshdlr;
7674 SCIP_CONSHDLRDATA* conshdlrdata;
7675
7676 conshdlr = SCIPconsGetHdlr(cons);
7677 assert(conshdlr != NULL);
7678
7679 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7680 assert(conshdlrdata != NULL);
7681
7682 /* catch bound change events of variables */
7683 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7684 assert(consdata->eventdata != NULL);
7685 }
7686
7687 *cutoff = FALSE;
7688
7689 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7690 if( !SCIPconsIsModifiable(cons) )
7691 {
7692 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7694 {
7695 SCIP_CALL( SCIPincConsAge(scip, cons) );
7696 }
7697
7698 /* tighten the variable's bounds */
7699 if( tightenbounds )
7700 {
7701 int oldnchgbds;
7702
7703 oldnchgbds = *nchgbds;
7704
7705 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7706
7707 if( *nchgbds > oldnchgbds )
7708 {
7710 }
7711 }
7712
7713 /* propagate ranged rows */
7714 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7715 {
7716 int nfixedvars;
7717 int naddconss;
7718 SCIPdebug( int oldnchgbds = *nchgbds; )
7719
7720 nfixedvars = 0;
7721 naddconss = 0;
7722
7723 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7724
7725 if( *cutoff )
7726 {
7727 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7728 }
7729 else
7730 {
7731 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7732 }
7733
7734 if( nfixedvars > 0 )
7735 *nchgbds += 2*nfixedvars;
7736 } /*lint !e438*/
7737
7738 /* check constraint for infeasibility and redundancy */
7739 if( !(*cutoff) )
7740 {
7741 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
7742 &isminsettoinfinity, &ismaxsettoinfinity);
7743
7744 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7745 {
7746 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7747 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7748
7749 /* analyze conflict */
7751
7753 *cutoff = TRUE;
7754 }
7755 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7756 {
7757 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7758 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7759
7760 /* analyze conflict */
7762
7764 *cutoff = TRUE;
7765 }
7766 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7767 {
7768 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7769 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7770
7771 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7772 if( consdata->nvars > 0 )
7774 else
7775 SCIP_CALL( SCIPdelCons(scip, cons) );
7776 }
7777 }
7778 }
7779
7780 return SCIP_OKAY;
7781}
7782
7783
7784/*
7785 * Presolving methods
7786 */
7787
7788/** converts all variables with fixed domain into FIXED variables */
7789static
7791 SCIP* scip, /**< SCIP data structure */
7792 SCIP_CONS* cons, /**< linear constraint */
7793 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7794 int* nfixedvars /**< pointer to count the total number of fixed variables */
7795 )
7796{
7797 SCIP_CONSDATA* consdata;
7798 SCIP_VAR* var;
7799 SCIP_VARSTATUS varstatus;
7800 SCIP_Real lb;
7801 SCIP_Real ub;
7802 SCIP_Bool fixed;
7803 SCIP_Bool infeasible;
7804 int v;
7805
7806 assert(scip != NULL);
7807 assert(cons != NULL);
7808 assert(cutoff != NULL);
7809 assert(nfixedvars != NULL);
7810
7811 consdata = SCIPconsGetData(cons);
7812 assert(consdata != NULL);
7813
7814 for( v = 0; v < consdata->nvars; ++v )
7815 {
7816 assert(consdata->vars != NULL);
7817 var = consdata->vars[v];
7818 varstatus = SCIPvarGetStatus(var);
7819
7820 if( varstatus != SCIP_VARSTATUS_FIXED )
7821 {
7822 lb = SCIPvarGetLbGlobal(var);
7823 ub = SCIPvarGetUbGlobal(var);
7824 if( SCIPisEQ(scip, lb, ub) )
7825 {
7826 SCIP_Real fixval;
7827
7828 fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7829 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7830 SCIPvarGetName(var), lb, ub, fixval);
7831 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7832 if( infeasible )
7833 {
7834 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7835 *cutoff = TRUE;
7836 return SCIP_OKAY;
7837 }
7838 if( fixed )
7839 (*nfixedvars)++;
7840 }
7841 }
7842 }
7843
7844 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7845
7846 if( infeasible )
7847 {
7848 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7849 *cutoff = TRUE;
7850 return SCIP_OKAY;
7851 }
7852
7853 assert(consdata->removedfixings);
7854
7855 return SCIP_OKAY;
7856}
7857
7858#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7859
7860/** extracts cliques of the constraint and adds them to SCIP
7861 *
7862 * The following clique extraction mechanism are implemeneted
7863 *
7864 * 1. collect binary variables and sort them in non increasing order, then
7865 *
7866 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7867 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7868 * condition
7869 *
7870 * minactivity + vals[i] + vals[i+1] > rhs
7871 *
7872 * and also add the binary to binary implication also for non-successive variables for which the same argument
7873 * holds
7874 *
7875 * minactivity + vals[i] + vals[j] > rhs
7876 *
7877 * e.g. 5.3 x1 + 3.6 x2 + 3.3 x3 + 2.1 x4 <= 5.5 (all x are binary) would lead to the clique (x1, x2, x3) and the
7878 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7879 *
7880 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7881 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7882 * condition
7883 *
7884 * maxactivity + vals[i] + vals[i-1] < lhs
7885 *
7886 * and also add the binary to binary implication also for non-successive variables for which the same argument
7887 * holds
7888 *
7889 * maxactivity + vals[i] + vals[j] < lhs
7890 *
7891 * e.g. you could multiply the above example by -1
7892 *
7893 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7894 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7895 * condition
7896 *
7897 * minactivity - vals[i] - vals[i-1] > rhs
7898 *
7899 * and also add the binary to binary implication also for non-successive variables for which the
7900 * same argument holds
7901 *
7902 * minactivity - vals[i] - vals[j] > rhs
7903 *
7904 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7905 * implication x1 = 0 => x3 = 1
7906 *
7907 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7908 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7909 * condition
7910 *
7911 * maxactivity - vals[i] - vals[i+1] < lhs
7912 *
7913 * and also add the binary to binary implication also for non-successive variables for which the same argument
7914 * holds
7915 *
7916 * maxactivity - vals[i] - vals[j] < lhs
7917 *
7918 * e.g. you could multiply the above example by -1
7919 *
7920 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7921 * as clique, (this part is done at the end of the method)
7922 *
7923 */
7924static
7926 SCIP* scip, /**< SCIP data structure */
7927 SCIP_CONS* cons, /**< linear constraint */
7928 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7929 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7930 int* nfixedvars, /**< pointer to count number of fixed variables */
7931 int* nchgbds, /**< pointer to count the total number of tightened bounds */
7932 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7933 )
7934{
7935 SCIP_VAR** vars;
7936 SCIP_Real* vals;
7937 SCIP_CONSDATA* consdata;
7938 SCIP_Bool lhsclique;
7939 SCIP_Bool rhsclique;
7940 SCIP_Bool finitelhs;
7941 SCIP_Bool finiterhs;
7942 SCIP_Bool finiteminact;
7943 SCIP_Bool finitemaxact;
7944 SCIP_Bool finitenegminact;
7945 SCIP_Bool finitenegmaxact;
7946 SCIP_Bool finiteposminact;
7947 SCIP_Bool finiteposmaxact;
7948 SCIP_Bool infeasible;
7949 SCIP_Bool stopped;
7950 int cliquenonzerosadded;
7951 int v;
7952 int i;
7953 int nposcoefs;
7954 int nnegcoefs;
7955 int nvars;
7956
7957 assert(scip != NULL);
7958 assert(cons != NULL);
7959 assert(nfixedvars != NULL);
7960 assert(nchgbds != NULL);
7961 assert(cutoff != NULL);
7962 assert(!SCIPconsIsDeleted(cons));
7963
7964 consdata = SCIPconsGetData(cons);
7965 assert(consdata != NULL);
7966
7967 if( consdata->nvars < 2 )
7968 return SCIP_OKAY;
7969
7970 /* add implications if possible
7971 *
7972 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7973 * maximal absolute contribution and also only if this variable would force all other variables to their bound
7974 * corresponding to the global minimal activity of the constraint
7975 */
7976 if( !consdata->implsadded )
7977 {
7978 /* sort variables by variable type */
7979 SCIP_CALL( consdataSort(scip, consdata) );
7980
7981 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7982 * up front, might change sorting correspondingly
7983 */
7984 /* fast abort if no binaries seem to exist
7985 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
7986 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
7987 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
7988 * which is the requirement for consdataSort() to actually resort the variables
7989 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
7990 */
7991 if( !SCIPvarIsBinary(consdata->vars[0]) )
7992 return SCIP_OKAY;
7993
7994 nvars = consdata->nvars;
7995 vars = consdata->vars;
7996 vals = consdata->vals;
7997
7998 /* recompute activities if needed */
7999 if( !consdata->validactivities )
8000 consdataCalcActivities(scip, consdata);
8001 assert(consdata->validactivities);
8002
8003 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8004 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8005 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8006 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8007 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8008 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8009 finiteminact = (finitenegminact && finiteposminact);
8010 finitemaxact = (finitenegmaxact && finiteposmaxact);
8011
8012 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8013 {
8014 SCIP_Real maxabscontrib = -1.0;
8015 SCIP_Bool posval = FALSE;
8016 SCIP_Bool allbinary = TRUE;
8017 int oldnchgbds = *nchgbds;
8018 int nbdchgs = 0;
8019 int nimpls = 0;
8020 int position = -1;
8021
8022 /* we need a valid minimal/maximal activity to add cliques */
8023 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8024 {
8026 assert(consdata->validglbminact);
8027 }
8028
8029 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8030 {
8032 assert(consdata->validglbmaxact);
8033 }
8034 assert(consdata->validglbminact || consdata->validglbmaxact);
8035
8036 /* @todo extend this to local/constraint probing */
8037
8038 /* determine maximal contribution to the activity */
8039 for( v = nvars - 1; v >= 0; --v )
8040 {
8041 if( SCIPvarIsBinary(vars[v]) )
8042 {
8043 if( vals[v] > 0 )
8044 {
8045 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8046
8047 if( value > maxabscontrib )
8048 {
8049 maxabscontrib = value;
8050 position = v;
8051 posval = TRUE;
8052 }
8053 }
8054 else
8055 {
8056 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8057
8058 value = REALABS(value);
8059
8060 if( value > maxabscontrib )
8061 {
8062 maxabscontrib = value;
8063 position = v;
8064 posval = FALSE;
8065 }
8066 }
8067 }
8068 else
8069 allbinary = FALSE;
8070 }
8071 assert(0 <= position && position < nvars);
8072
8073 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8074 {
8075 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8076 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8077 * implications
8078 */
8079 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8080 {
8081 for( v = nvars - 1; v >= 0; --v )
8082 {
8083 /* binary to binary implications will be collected when extrating cliques */
8084 if( !SCIPvarIsBinary(vars[v]) )
8085 {
8086 if( v != position )
8087 {
8088 if( vals[v] > 0 )
8089 {
8090 /* add implications */
8091 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8092 ++nimpls;
8093 *nchgbds += nbdchgs;
8094 }
8095 else
8096 {
8097 /* add implications */
8098 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8099 ++nimpls;
8100 *nchgbds += nbdchgs;
8101 }
8102
8103 if( infeasible )
8104 {
8105 *cutoff = TRUE;
8106 break;
8107 }
8108 }
8109 }
8110 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8111 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8112 break;
8113 }
8114 }
8115
8116 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8117 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8118 * implications
8119 */
8120 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8121 {
8122 for( v = nvars - 1; v >= 0; --v )
8123 {
8124 /* binary to binary implications will be collected when extrating cliques */
8125 if( !SCIPvarIsBinary(vars[v]) )
8126 {
8127 if( v != position )
8128 {
8129 if( vals[v] > 0 )
8130 {
8131 /* add implications */
8132 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8133 ++nimpls;
8134 *nchgbds += nbdchgs;
8135 }
8136 else
8137 {
8138 /* add implications */
8139 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8140 ++nimpls;
8141 *nchgbds += nbdchgs;
8142 }
8143
8144 if( infeasible )
8145 {
8146 *cutoff = TRUE;
8147 break;
8148 }
8149 }
8150 }
8151 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8152 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8153 break;
8154 }
8155 }
8156
8157 /* did we find some implications */
8158 if( nimpls > 0 )
8159 {
8160 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8161
8162 if( *cutoff )
8163 return SCIP_OKAY;
8164
8165 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8166 if( *nchgbds - oldnchgbds > 0 )
8167 {
8168 /* check for fixed variables */
8169 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8170 if( *cutoff )
8171 return SCIP_OKAY;
8172
8173 /* tighten variable's bounds */
8174 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8175 if( *cutoff )
8176 return SCIP_OKAY;
8177
8178 /* check for fixed variables */
8179 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8180 if( *cutoff )
8181 return SCIP_OKAY;
8182 }
8183 }
8184 }
8185 }
8186
8187 consdata->implsadded = TRUE;
8188 }
8189
8190 /* check if we already added the cliques of this constraint */
8191 if( consdata->cliquesadded )
8192 return SCIP_OKAY;
8193
8194 consdata->cliquesadded = TRUE;
8195 cliquenonzerosadded = 0;
8196 stopped = FALSE;
8197
8198 /* sort variables by variable type */
8199 SCIP_CALL( consdataSort(scip, consdata) );
8200
8201 nvars = consdata->nvars;
8202 vars = consdata->vars;
8203 vals = consdata->vals;
8204
8205 /**@todo extract more cliques, implications and variable bounds from linear constraints */
8206
8207 /* recompute activities if needed */
8208 if( !consdata->validactivities )
8209 consdataCalcActivities(scip, consdata);
8210 assert(consdata->validactivities);
8211
8212 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8213 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8214 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8215 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8216 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8217 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8218 finiteminact = (finitenegminact && finiteposminact);
8219 finitemaxact = (finitenegmaxact && finiteposmaxact);
8220
8221 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8222 * information
8223 */
8224 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8225 {
8226 SCIP_VAR** binvars;
8227 SCIP_Real* binvarvals;
8228 int nposbinvars = 0;
8229 int nnegbinvars = 0;
8230 int allonebinary = 0;
8231
8232 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8233 SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8234
8235 /* collect binary variables */
8236 for( i = 0; i < nvars; ++i )
8237 {
8238 if( SCIPvarIsBinary(vars[i]) )
8239 {
8240 assert(!SCIPisZero(scip, vals[i]));
8241
8242 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8243 ++allonebinary;
8244
8245 binvars[nposbinvars + nnegbinvars] = vars[i];
8246 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8247
8248 if( SCIPisPositive(scip, vals[i]) )
8249 ++nposbinvars;
8250 else
8251 ++nnegbinvars;
8252
8253 assert(nposbinvars + nnegbinvars <= nvars);
8254 }
8255 /* stop searching for binary variables, because the constraint data is sorted */
8256 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8257 break;
8258 }
8259 assert(nposbinvars + nnegbinvars <= nvars);
8260
8261 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8262 * cliques
8263 */
8264 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8265 {
8266 SCIP_Real threshold;
8267 int oldnchgbds = *nchgbds;
8268 int nbdchgs;
8269 int jstart;
8270 int j;
8271
8272 /* we need a valid minimal/maximal activity to add cliques */
8273 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8274 {
8276 assert(consdata->validglbminact);
8277 }
8278
8279 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8280 {
8282 assert(consdata->validglbmaxact);
8283 }
8284 assert(consdata->validglbminact || consdata->validglbmaxact);
8285
8286 /* sort coefficients non-increasing to be faster in the clique search */
8287 SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8288
8289 /* case a) */
8290 if( finiterhs && finitenegminact && nposbinvars >= 2 )
8291 {
8292 /* compute value that needs to be exceeded */
8293 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8294
8295 j = 1;
8296#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8297 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8298 assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8299#endif
8300 /* check if at least two variables are in a clique */
8301 if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8302 {
8303 ++j;
8304 /* check for extending the clique */
8305 while( j < nposbinvars )
8306 {
8307 if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8308 break;
8309 ++j;
8310 }
8311 assert(j >= 2);
8312
8313 /* add clique with at least two variables */
8314 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8315
8316 if( infeasible )
8317 *cutoff = TRUE;
8318
8319 *nchgbds += nbdchgs;
8320
8321 cliquenonzerosadded += j;
8322 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8323 stopped = TRUE;
8324
8325 /* exchange the last variable in the clique if possible and add all new ones */
8326 if( !stopped && !(*cutoff) && j < nposbinvars )
8327 {
8328 SCIP_VAR** clqvars;
8329 int lastfit = j - 2;
8330 assert(lastfit >= 0);
8331
8332 /* copy all 'main'-clique variables */
8333 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8334
8335 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8336 while( lastfit >= 0 && j < nposbinvars )
8337 {
8338 /* check if two variables are in a clique */
8339 if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8340 {
8341 clqvars[lastfit + 1] = binvars[j];
8342
8343 /* add clique with at least two variables */
8344 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8345
8346 if( infeasible )
8347 {
8348 *cutoff = TRUE;
8349 break;
8350 }
8351
8352 *nchgbds += nbdchgs;
8353
8354 cliquenonzerosadded += (lastfit + 2);
8355 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8356 {
8357 stopped = TRUE;
8358 break;
8359 }
8360
8361 ++j;
8362 }
8363 else
8364 --lastfit;
8365 }
8366
8367 SCIPfreeBufferArray(scip, &clqvars);
8368 }
8369 }
8370 }
8371
8372 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8373 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8374 {
8375 /* check for fixed variables */
8376 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8377
8378 if( !*cutoff )
8379 {
8380 /* tighten variable's bounds */
8381 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8382
8383 if( !*cutoff )
8384 {
8385 /* check for fixed variables */
8386 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8387
8388 if( !*cutoff )
8389 {
8390 /* sort variables by variable type */
8391 SCIP_CALL( consdataSort(scip, consdata) );
8392
8393 /* recompute activities if needed */
8394 if( !consdata->validactivities )
8395 consdataCalcActivities(scip, consdata);
8396 assert(consdata->validactivities);
8397
8398 nvars = consdata->nvars;
8399 vars = consdata->vars;
8400 vals = consdata->vals;
8401 nposbinvars = 0;
8402 nnegbinvars = 0;
8403 allonebinary = 0;
8404
8405 /* update binary variables */
8406 for( i = 0; i < nvars; ++i )
8407 {
8408 if( SCIPvarIsBinary(vars[i]) )
8409 {
8410 assert(!SCIPisZero(scip, vals[i]));
8411
8412 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8413 ++allonebinary;
8414
8415 binvars[nposbinvars + nnegbinvars] = vars[i];
8416 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8417
8418 if( SCIPisPositive(scip, vals[i]) )
8419 ++nposbinvars;
8420 else
8421 ++nnegbinvars;
8422
8423 assert(nposbinvars + nnegbinvars <= nvars);
8424 }
8425 /* stop searching for binary variables, because the constraint data is sorted */
8426 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8427 break;
8428 }
8429 assert(nposbinvars + nnegbinvars <= nvars);
8430 }
8431 }
8432 }
8433
8434 oldnchgbds = *nchgbds;
8435 }
8436
8437 /* case b) */
8438 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8439 {
8440 /* compute value that needs to be deceeded */
8441 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8442
8443 i = nposbinvars + nnegbinvars - 1;
8444 j = i - 1;
8445#ifdef SCIP_DISABLED_CODE
8446 /* assertion should only hold when constraints were fully propagated and boundstightened */
8447 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8448 assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8449#endif
8450 /* check if two variables are in a clique */
8451 if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8452 {
8453 --j;
8454 /* check for extending the clique */
8455 while( j >= nposbinvars )
8456 {
8457 if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8458 break;
8459 --j;
8460 }
8461 jstart = j;
8462
8463 assert(i - j >= 2);
8464 /* add clique with at least two variables */
8465 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8466
8467 if( infeasible )
8468 *cutoff = TRUE;
8469
8470 *nchgbds += nbdchgs;
8471
8472 cliquenonzerosadded += (i - j);
8473 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8474 stopped = TRUE;
8475
8476 /* exchange the last variable in the clique if possible and add all new ones */
8477 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8478 {
8479 SCIP_VAR** clqvars;
8480 int lastfit = jstart + 1;
8481 assert(lastfit < i);
8482
8483 /* copy all 'main'-clique variables */
8484 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8485 ++lastfit;
8486
8487 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8488 while( lastfit <= i && j >= nposbinvars )
8489 {
8490 /* check if two variables are in a clique */
8491 if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8492 {
8493 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8494 clqvars[lastfit - jstart - 2] = binvars[j];
8495
8496 assert(i - lastfit + 2 >= 2);
8497 /* add clique with at least two variables */
8498 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8499
8500 if( infeasible )
8501 {
8502 *cutoff = TRUE;
8503 break;
8504 }
8505
8506 *nchgbds += nbdchgs;
8507
8508 cliquenonzerosadded += (i - lastfit + 2);
8509 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8510 {
8511 stopped = TRUE;
8512 break;
8513 }
8514
8515 --j;
8516 }
8517 else
8518 ++lastfit;
8519 }
8520
8521 SCIPfreeBufferArray(scip, &clqvars);
8522 }
8523 }
8524 }
8525
8526 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8527 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8528 {
8529 /* check for fixed variables */
8530 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8531
8532 if( !*cutoff )
8533 {
8534 /* tighten variable's bounds */
8535 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8536
8537 if( !*cutoff )
8538 {
8539 /* check for fixed variables */
8540 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8541
8542 if( !*cutoff )
8543 {
8544 /* sort variables by variable type */
8545 SCIP_CALL( consdataSort(scip, consdata) );
8546
8547 /* recompute activities if needed */
8548 if( !consdata->validactivities )
8549 consdataCalcActivities(scip, consdata);
8550 assert(consdata->validactivities);
8551
8552 nvars = consdata->nvars;
8553 vars = consdata->vars;
8554 vals = consdata->vals;
8555 nposbinvars = 0;
8556 nnegbinvars = 0;
8557 allonebinary = 0;
8558
8559 /* update binary variables */
8560 for( i = 0; i < nvars; ++i )
8561 {
8562 if( SCIPvarIsBinary(vars[i]) )
8563 {
8564 assert(!SCIPisZero(scip, vals[i]));
8565
8566 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8567 ++allonebinary;
8568
8569 binvars[nposbinvars + nnegbinvars] = vars[i];
8570 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8571
8572 if( SCIPisPositive(scip, vals[i]) )
8573 ++nposbinvars;
8574 else
8575 ++nnegbinvars;
8576
8577 assert(nposbinvars + nnegbinvars <= nvars);
8578 }
8579 /* stop searching for binary variables, because the constraint data is sorted */
8580 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8581 break;
8582 }
8583 assert(nposbinvars + nnegbinvars <= nvars);
8584 }
8585 }
8586 }
8587
8588 oldnchgbds = *nchgbds;
8589 }
8590
8591 /* case c) */
8592 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8593 {
8594 SCIP_Bool* values;
8595
8596 /* initialize clique values array for adding a negated clique */
8597 SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8598 BMSclearMemoryArray(values, nnegbinvars);
8599
8600 /* compute value that needs to be exceeded */
8601 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8602
8603 i = nposbinvars + nnegbinvars - 1;
8604 j = i - 1;
8605
8606#ifdef SCIP_DISABLED_CODE
8607 /* assertion should only hold when constraints were fully propagated and boundstightened */
8608 /* check if the variable should not have already been fixed to one */
8609 assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8610#endif
8611
8612 if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8613 {
8614 --j;
8615 /* check for extending the clique */
8616 while( j >= nposbinvars )
8617 {
8618 if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8619 break;
8620 --j;
8621 }
8622 jstart = j;
8623
8624 assert(i - j >= 2);
8625 /* add negated clique with at least two variables */
8626 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8627
8628 if( infeasible )
8629 *cutoff = TRUE;
8630
8631 *nchgbds += nbdchgs;
8632
8633 cliquenonzerosadded += (i - j);
8634 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8635 stopped = TRUE;
8636
8637 /* exchange the last variable in the clique if possible and add all new ones */
8638 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8639 {
8640 SCIP_VAR** clqvars;
8641 int lastfit = j + 1;
8642 assert(lastfit < i);
8643
8644 /* copy all 'main'-clique variables */
8645 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8646 ++lastfit;
8647
8648 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8649 while( lastfit <= i && j >= nposbinvars )
8650 {
8651 /* check if two variables are in a negated clique */
8652 if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8653 {
8654 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8655 clqvars[lastfit - jstart - 2] = binvars[j];
8656
8657 assert(i - lastfit + 2 >= 2);
8658 /* add clique with at least two variables */
8659 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8660
8661 if( infeasible )
8662 {
8663 *cutoff = TRUE;
8664 break;
8665 }
8666
8667 *nchgbds += nbdchgs;
8668
8669 cliquenonzerosadded += (i - lastfit + 2);
8670 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8671 {
8672 stopped = TRUE;
8673 break;
8674 }
8675
8676 --j;
8677 }
8678 else
8679 ++lastfit;
8680 }
8681
8682 SCIPfreeBufferArray(scip, &clqvars);
8683 }
8684 }
8685
8686 SCIPfreeBufferArray(scip, &values);
8687 }
8688
8689 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8690 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8691 {
8692 /* check for fixed variables */
8693 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8694
8695 if( !*cutoff )
8696 {
8697 /* tighten variable's bounds */
8698 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8699
8700 if( !*cutoff )
8701 {
8702 /* check for fixed variables */
8703 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8704
8705 if( !*cutoff )
8706 {
8707 /* sort variables by variable type */
8708 SCIP_CALL( consdataSort(scip, consdata) );
8709
8710 /* recompute activities if needed */
8711 if( !consdata->validactivities )
8712 consdataCalcActivities(scip, consdata);
8713 assert(consdata->validactivities);
8714
8715 nvars = consdata->nvars;
8716 vars = consdata->vars;
8717 vals = consdata->vals;
8718 nposbinvars = 0;
8719 nnegbinvars = 0;
8720 allonebinary = 0;
8721
8722 /* update binary variables */
8723 for( i = 0; i < nvars; ++i )
8724 {
8725 if( SCIPvarIsBinary(vars[i]) )
8726 {
8727 assert(!SCIPisZero(scip, vals[i]));
8728
8729 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8730 ++allonebinary;
8731
8732 binvars[nposbinvars + nnegbinvars] = vars[i];
8733 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8734
8735 if( SCIPisPositive(scip, vals[i]) )
8736 ++nposbinvars;
8737 else
8738 ++nnegbinvars;
8739
8740 assert(nposbinvars + nnegbinvars <= nvars);
8741 }
8742 /* stop searching for binary variables, because the constraint data is sorted */
8743 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8744 break;
8745 }
8746 assert(nposbinvars + nnegbinvars <= nvars);
8747 }
8748 }
8749 }
8750 }
8751
8752 /* case d) */
8753 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8754 {
8755 SCIP_Bool* values;
8756
8757 /* initialize clique values array for adding a negated clique */
8758 SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8759 BMSclearMemoryArray(values, nposbinvars);
8760
8761 /* compute value that needs to be exceeded */
8762 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8763
8764 j = 1;
8765
8766#ifdef SCIP_DISABLED_CODE
8767 /* assertion should only hold when constraints were fully propagated and boundstightened */
8768 /* check if the variable should not have already been fixed to one */
8769 assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8770#endif
8771
8772 if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8773 {
8774 ++j;
8775 /* check for extending the clique */
8776 while( j < nposbinvars )
8777 {
8778 if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8779 break;
8780 ++j;
8781 }
8782 assert(j >= 2);
8783
8784 /* add negated clique with at least two variables */
8785 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8786
8787 if( infeasible )
8788 *cutoff = TRUE;
8789
8790 *nchgbds += nbdchgs;
8791
8792 cliquenonzerosadded += j;
8793 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8794 stopped = TRUE;
8795
8796 /* exchange the last variable in the clique if possible and add all new ones */
8797 if( !stopped && !(*cutoff) && j < nposbinvars )
8798 {
8799 SCIP_VAR** clqvars;
8800 int lastfit = j - 2;
8801 assert(lastfit >= 0);
8802
8803 /* copy all 'main'-clique variables */
8804 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8805
8806 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8807 while( lastfit >= 0 && j < nposbinvars )
8808 {
8809 /* check if two variables are in a negated clique */
8810 if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8811 {
8812 clqvars[lastfit + 1] = binvars[j];
8813
8814 /* add clique with at least two variables */
8815 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8816
8817 if( infeasible )
8818 {
8819 *cutoff = TRUE;
8820 break;
8821 }
8822
8823 *nchgbds += nbdchgs;
8824
8825 cliquenonzerosadded += lastfit + 2;
8826 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8827 break;
8828
8829 ++j;
8830 }
8831 else
8832 --lastfit;
8833 }
8834
8835 SCIPfreeBufferArray(scip, &clqvars);
8836 }
8837 }
8838
8839 SCIPfreeBufferArray(scip, &values);
8840 }
8841 }
8842
8843 SCIPfreeBufferArray(scip, &binvarvals);
8844 SCIPfreeBufferArray(scip, &binvars);
8845
8846 if( *cutoff )
8847 return SCIP_OKAY;
8848 }
8849
8850 /* 2. we only check if the constraint is a set packing / partitioning constraint */
8851
8852 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8853 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8854 */
8855 nposcoefs = 0;
8856 nnegcoefs = 0;
8857 for( i = 0; i < nvars; ++i )
8858 {
8859 if( !SCIPvarIsBinary(vars[i]) )
8860 return SCIP_OKAY;
8861 else if( SCIPisEQ(scip, vals[i], +1.0) )
8862 nposcoefs++;
8863 else if( SCIPisEQ(scip, vals[i], -1.0) )
8864 nnegcoefs++;
8865 else
8866 return SCIP_OKAY;
8867 }
8868
8869 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8870 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8871
8872 if( lhsclique || rhsclique )
8873 {
8874 SCIP_Bool* values;
8875 int nbdchgs;
8876
8877 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8878 SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8879 SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8880
8881 for( i = 0; i < nvars; ++i )
8882 values[i] = (rhsclique == (vals[i] > 0.0));
8883
8884 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8885
8886 if( infeasible )
8887 *cutoff = TRUE;
8888
8889 *nchgbds += nbdchgs;
8890 SCIPfreeBufferArray(scip, &values);
8891 }
8892
8893 return SCIP_OKAY;
8894}
8895
8896/** tightens left and right hand side of constraint due to integrality */
8897static
8899 SCIP* scip, /**< SCIP data structure */
8900 SCIP_CONS* cons, /**< linear constraint */
8901 int* nchgsides, /**< pointer to count number of side changes */
8902 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8903 )
8904{
8905 SCIP_CONSDATA* consdata;
8906 SCIP_Real newlhs;
8907 SCIP_Real newrhs;
8908 SCIP_Bool chglhs;
8909 SCIP_Bool chgrhs;
8910 SCIP_Bool integral;
8911 int i;
8912
8913 assert(scip != NULL);
8914 assert(cons != NULL);
8915 assert(nchgsides != NULL);
8916 assert(infeasible != NULL);
8917
8918 consdata = SCIPconsGetData(cons);
8919 assert(consdata != NULL);
8920
8921 *infeasible = FALSE;
8922
8923 chglhs = FALSE;
8924 chgrhs = FALSE;
8925 newlhs = -SCIPinfinity(scip);
8926 newrhs = SCIPinfinity(scip);
8927
8928 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8929 {
8930 integral = TRUE;
8931 for( i = 0; i < consdata->nvars && integral; ++i )
8932 {
8933 integral = SCIPisIntegral(scip, consdata->vals[i])
8934 && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
8935 }
8936 if( integral )
8937 {
8938 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8939 {
8940 newlhs = SCIPfeasCeil(scip, consdata->lhs);
8941 chglhs = TRUE;
8942 }
8943 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8944 {
8945 newrhs = SCIPfeasFloor(scip, consdata->rhs);
8946 chgrhs = TRUE;
8947 }
8948
8949 /* check whether rounding would lead to an unsatisfiable constraint */
8950 if( SCIPisGT(scip, newlhs, newrhs) )
8951 {
8952 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
8953 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
8954
8955 *infeasible = TRUE;
8956 return SCIP_OKAY;
8957 }
8958
8959 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8960 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8961
8962 if( chglhs )
8963 {
8964 assert(!SCIPisInfinity(scip, -newlhs));
8965
8966 SCIP_CALL( chgLhs(scip, cons, newlhs) );
8967 if( !consdata->upgraded )
8968 (*nchgsides)++;
8969 }
8970 if( chgrhs )
8971 {
8972 assert(!SCIPisInfinity(scip, newrhs));
8973
8974 SCIP_CALL( chgRhs(scip, cons, newrhs) );
8975 if( !consdata->upgraded )
8976 (*nchgsides)++;
8977 }
8978 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8979 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8980 }
8981 }
8982
8983 return SCIP_OKAY;
8984}
8985
8986/** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
8987 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
8988 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
8989 * (i) ai >= 0:
8990 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
8991 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
8992 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8993 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8994 * - change coefficients:
8995 * ai' := max(lhs - minact, maxact - rhs, 0)
8996 * lhs' := lhs - (ai - ai')*li
8997 * rhs' := rhs - (ai - ai')*ui
8998 * (ii) ai < 0:
8999 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9000 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9001 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9002 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9003 * - change coefficients:
9004 * ai' := min(rhs - maxact, minact - lhs, 0)
9005 * lhs' := lhs - (ai - ai')*ui
9006 * rhs' := rhs - (ai - ai')*li
9007 *
9008 * We further try to remove variables from the constraint;
9009 * Variables which fulfill conditions (**) or (***) are called relevant variables.
9010 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9011 * variables are set to their "worst" bound. If all variables which are not relevant cannot make the lhs/rhs
9012 * redundant, even if they are set to their "best" bound, they can be removed from the constraint. E.g., for binary
9013 * variables and an inequality x_1 +x_2 +10y_1 +10y_2 >= 5, setting either of the y_i to one suffices to fulfill the
9014 * inequality, whereas the x_i do not contribute to feasibility and can be removed.
9015 *
9016 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9017 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9018 */
9019static
9021 SCIP* scip, /**< SCIP data structure */
9022 SCIP_CONS* cons, /**< linear constraint */
9023 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9024 int* nchgsides /**< pointer to count number of side changes */
9025 )
9026{
9027 SCIP_CONSDATA* consdata;
9028 SCIP_VAR* var;
9029 SCIP_Bool* isvarrelevant;
9030 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9031 * activity, ignoring the coefficients contributing with infinite value */
9032 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9033 * activity, ignoring the coefficients contributing with infinite value */
9034 SCIP_Bool isminacttight; /* are all contributions to the minactivity non-huge or non-contradicting? */
9035 SCIP_Bool ismaxacttight; /* are all contributions to the maxactivity non-huge or non-contradicting? */
9036 SCIP_Bool isminsettoinfinity;
9037 SCIP_Bool ismaxsettoinfinity;
9038 SCIP_Real minleftactivity; /* minimal activity without relevant variables */
9039 SCIP_Real maxleftactivity; /* maximal activity without relevant variables */
9040 SCIP_Real aggrlhs; /* lhs without minimal activity of relevant variables */
9041 SCIP_Real aggrrhs; /* rhs without maximal activity of relevant variables */
9042 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9043 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9044 SCIP_Real val;
9045 SCIP_Real newval;
9046 SCIP_Real newlhs;
9047 SCIP_Real newrhs;
9048 SCIP_Real lb;
9049 SCIP_Real ub;
9050 int i;
9051
9052 assert(scip != NULL);
9053 assert(cons != NULL);
9054 assert(nchgcoefs != NULL);
9055 assert(nchgsides != NULL);
9056
9057 consdata = SCIPconsGetData(cons);
9058 assert(consdata != NULL);
9059
9060 /* allocate relevance flags */
9061 SCIP_CALL( SCIPallocBufferArray(scip, &isvarrelevant, consdata->nvars) );
9062
9063 /* @todo Is this still needed with automatic recomputation of activities? */
9064 /* if the maximal coefficient is too large, recompute the activities */
9065 if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9066 || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9067 {
9070 }
9071
9072 /* get the minimal and maximal activity of the constraint */
9073 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9074 &isminsettoinfinity, &ismaxsettoinfinity);
9075 assert(( isminsettoinfinity && !SCIPisInfinity(scip, -consdata->lhs) )
9076 || SCIPisLT(scip, minactivity, consdata->lhs)
9077 || ( ismaxsettoinfinity && !SCIPisInfinity(scip, consdata->rhs) )
9078 || SCIPisGT(scip, maxactivity, consdata->rhs));
9079
9080 minleftactivity = 0.0;
9081 maxleftactivity = 0.0;
9082
9083 /* try to tighten each coefficient */
9084 i = 0;
9085 while( i < consdata->nvars )
9086 {
9087 /* get coefficient and variable's bounds */
9088 var = consdata->vars[i];
9089 val = consdata->vals[i];
9090 assert(!SCIPisZero(scip, val));
9091 lb = SCIPvarGetLbLocal(var);
9092 ub = SCIPvarGetUbLocal(var);
9093
9094 /* check sign of coefficient */
9095 if( val >= 0.0 )
9096 {
9097 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9098 isvarrelevant[i] = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS
9099 && SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs);
9100
9101 if( isvarrelevant[i] )
9102 {
9103 /* change coefficients:
9104 * ai' := max(lhs - minact, maxact - rhs)
9105 * lhs' := lhs - (ai - ai')*li
9106 * rhs' := rhs - (ai - ai')*ui
9107 */
9108
9109 lval = consdata->lhs - minactivity;
9110 rval = maxactivity - consdata->rhs;
9111
9112 /* Try to avoid cancellation, if there are only two variables */
9113 if( consdata->nvars == 2 )
9114 {
9115 SCIP_Real otherval;
9116 otherval = consdata->vals[1-i];
9117
9118 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9119 {
9120 lval = consdata->lhs - val*lb;
9121 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9122 }
9123
9124 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9125 {
9126 rval = val*ub - consdata->rhs;
9127 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9128 }
9129 }
9130
9131 newval = MAX3(lval, rval, 0.0);
9132 assert(SCIPisSumRelLE(scip, newval, val));
9133
9134 /* Try to avoid cancellation in computation of lhs/rhs */
9135 newlhs = consdata->lhs - val * lb;
9136 newlhs += newval * lb;
9137 newrhs = consdata->rhs - val * ub;
9138 newrhs += newval * ub;
9139
9140 if( !SCIPisSumRelEQ(scip, newval, val) )
9141 {
9142 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9143 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9144 maxactivity, consdata->lhs, consdata->rhs);
9145
9146 /* update the coefficient and the activity bounds */
9147 if( SCIPisZero(scip, newval) )
9148 {
9149 SCIP_CALL( delCoefPos(scip, cons, i) );
9150 --i;
9151 }
9152 else
9153 {
9154 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9155 }
9156 ++(*nchgcoefs);
9157
9158 /* get the new minimal and maximal activity of the constraint */
9159 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9160 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9161
9162 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9163 {
9164 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9165 consdata->lhs, newlhs);
9166
9167 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9168 (*nchgsides)++;
9169 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9170 }
9171
9172 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9173 {
9174 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9175 consdata->rhs, newrhs);
9176
9177 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9178 (*nchgsides)++;
9179 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9180 }
9181 }
9182 }
9183 else
9184 {
9185 if( !SCIPisInfinity(scip, -minleftactivity) )
9186 {
9187 assert(!SCIPisInfinity(scip, val));
9188 assert(!SCIPisInfinity(scip, lb));
9189 if( SCIPisInfinity(scip, -lb) )
9190 minleftactivity = -SCIPinfinity(scip);
9191 else
9192 minleftactivity += val * lb;
9193 }
9194
9195 if( !SCIPisInfinity(scip, maxleftactivity) )
9196 {
9197 assert(!SCIPisInfinity(scip, val));
9198 assert(!SCIPisInfinity(scip, -ub));
9199 if( SCIPisInfinity(scip,ub) )
9200 maxleftactivity = SCIPinfinity(scip);
9201 else
9202 maxleftactivity += val * ub;
9203 }
9204 }
9205 }
9206 else
9207 {
9208 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9209 isvarrelevant[i] = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS
9210 && SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs);
9211
9212 if( isvarrelevant[i] )
9213 {
9214 /* change coefficients:
9215 * ai' := min(rhs - maxact, minact - lhs)
9216 * lhs' := lhs - (ai - ai')*ui
9217 * rhs' := rhs - (ai - ai')*li
9218 */
9219
9220 lval = minactivity - consdata->lhs;
9221 rval = consdata->rhs - maxactivity;
9222
9223 /* Try to avoid cancellation, if there are only two variables */
9224 if( consdata->nvars == 2 )
9225 {
9226 SCIP_Real otherval;
9227 otherval = consdata->vals[1-i];
9228
9229 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9230 {
9231 lval = val*ub - consdata->lhs;
9232 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9233 }
9234
9235 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9236 {
9237 rval = consdata->rhs - val*lb;
9238 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9239 }
9240 }
9241
9242 newval = MIN3(lval, rval, 0.0);
9243 assert(SCIPisSumRelGE(scip, newval, val));
9244
9245 /* Try to avoid cancellation in computation of lhs/rhs */
9246 newlhs = consdata->lhs - val * ub;
9247 newlhs += newval * ub;
9248 newrhs = consdata->rhs - val * lb;
9249 newrhs += newval * lb;
9250
9251 if( !SCIPisSumRelEQ(scip, newval, val) )
9252 {
9253 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9254 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9255 maxactivity, consdata->lhs, consdata->rhs);
9256
9257 /* update the coefficient and the activity bounds */
9258 if( SCIPisZero(scip, newval) )
9259 {
9260 SCIP_CALL( delCoefPos(scip, cons, i) );
9261 --i;
9262 }
9263 else
9264 {
9265 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9266 }
9267 ++(*nchgcoefs);
9268
9269 /* get the new minimal and maximal activity of the constraint */
9270 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9271 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9272
9273 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9274 {
9275 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9276 consdata->lhs, newlhs);
9277
9278 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9279 (*nchgsides)++;
9280 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9281 }
9282
9283 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9284 {
9285 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9286 consdata->rhs, newrhs);
9287
9288 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9289 (*nchgsides)++;
9290 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9291 }
9292 }
9293 }
9294 else
9295 {
9296 if( !SCIPisInfinity(scip, -minleftactivity) )
9297 {
9298 assert(!SCIPisInfinity(scip, -val));
9299 assert(!SCIPisInfinity(scip, -ub));
9300 if( SCIPisInfinity(scip, ub) )
9301 minleftactivity = -SCIPinfinity(scip);
9302 else
9303 minleftactivity += val * ub;
9304 }
9305
9306 if( !SCIPisInfinity(scip, maxleftactivity) )
9307 {
9308 assert(!SCIPisInfinity(scip, -val));
9309 assert(!SCIPisInfinity(scip, lb));
9310 if( SCIPisInfinity(scip, -lb) )
9311 maxleftactivity = SCIPinfinity(scip);
9312 else
9313 maxleftactivity += val * lb;
9314 }
9315 }
9316 }
9317
9318 ++i;
9319 }
9320
9321 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9322 minleftactivity, consdata->rhs);
9323 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9324 maxleftactivity, consdata->lhs);
9325
9326 /* minleft == \infty ==> minactivity == \infty */
9327 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9328 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9329
9330 /* if the lhs is finite, we will check in the following whether the not relevant variables can make lhs feasible;
9331 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9332 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9333 * (<= the exact minactivity), and we might falsely remove coefficients in the following
9334 */
9335 assert(!SCIPisInfinity(scip, minactivity));
9336 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
9337 goto TERMINATE;
9338
9339 /* if the rhs is finite, we will check in the following whether the not relevant variables can make rhs feasible;
9340 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9341 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9342 * (>= the exact maxactivity), and we might falsely remove coefficients in the following
9343 */
9344 assert(!SCIPisInfinity(scip, -maxactivity));
9345 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
9346 goto TERMINATE;
9347
9348 /* correct lhs and rhs by min/max activity of relevant variables
9349 * relevant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9350 */
9351 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9352 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9353
9354 /* check if the constraint contains variables whose coefficient can be removed. The reasoning is the following:
9355 * Each relevant variable can make the lhs/rhs feasible with a deviation of only one in the bound. If _all_ not
9356 * relevant variables together cannot make lhs/rhs redundant, they can be removed from the constraint. aggrrhs may
9357 * contain some near-infinity value, but only if rhs is infinity.
9358 */
9359 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9360 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9361 {
9362 SCIP_Real minleftactivitypart;
9363 SCIP_Real maxleftactivitypart;
9364
9365 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9366
9367 /* remove redundant variables from constraint */
9368 i = 0;
9369 while( i < consdata->nvars )
9370 {
9371 /* consider redundant variable */
9372 if( !isvarrelevant[i] )
9373 {
9374 /* get coefficient and variable's bounds */
9375 var = consdata->vars[i];
9376 val = consdata->vals[i];
9377 assert(!SCIPisZero(scip, val));
9378 lb = SCIPvarGetLbLocal(var);
9379 ub = SCIPvarGetUbLocal(var);
9380
9381 SCIPdebugMsg(scip, "val = %g\tlhs = %g\trhs = %g\n", val, consdata->lhs, consdata->rhs);
9382 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> from constraint since it is redundant\n",
9383 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
9384
9385 /* check sign of coefficient */
9386 if( val >= 0.0 )
9387 {
9388 minleftactivitypart = val * lb;
9389 maxleftactivitypart = val * ub;
9390 }
9391 else
9392 {
9393 minleftactivitypart = val * ub;
9394 maxleftactivitypart = val * lb;
9395 }
9396
9397 /* remove redundant variable */
9398 isvarrelevant[i] = isvarrelevant[consdata->nvars - 1];
9399 SCIP_CALL( delCoefPos(scip, cons, i) );
9400 --i;
9401
9402 /* adjust lhs and right hand side */
9403 newlhs = consdata->lhs - minleftactivitypart;
9404 newrhs = consdata->rhs - maxleftactivitypart;
9405
9406 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9407 {
9408 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9409 consdata->lhs, newlhs);
9410
9411 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9412 ++(*nchgsides);
9413 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9414 }
9415
9416 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9417 {
9418 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9419 consdata->rhs, newrhs);
9420
9421 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9422 ++(*nchgsides);
9423 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9424 }
9425 }
9426
9427 ++i;
9428 }
9429 }
9430
9431TERMINATE:
9432 /* free relevance flags */
9433 SCIPfreeBufferArray(scip, &isvarrelevant);
9434
9435 return SCIP_OKAY;
9436}
9437
9438/** processes equality with only one variable by fixing the variable and deleting the constraint */
9439static
9441 SCIP* scip, /**< SCIP data structure */
9442 SCIP_CONS* cons, /**< linear constraint */
9443 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9444 int* nfixedvars, /**< pointer to count number of fixed variables */
9445 int* ndelconss /**< pointer to count number of deleted constraints */
9446 )
9447{
9448 SCIP_CONSDATA* consdata;
9449 SCIP_VAR* var;
9450 SCIP_Real val;
9451 SCIP_Real fixval;
9452 SCIP_Bool infeasible;
9453 SCIP_Bool fixed;
9454
9455 assert(scip != NULL);
9456 assert(cons != NULL);
9457 assert(cutoff != NULL);
9458 assert(nfixedvars != NULL);
9459 assert(ndelconss != NULL);
9460
9461 consdata = SCIPconsGetData(cons);
9462 assert(consdata != NULL);
9463 assert(consdata->nvars == 1);
9464 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9465
9466 /* calculate the value to fix the variable to */
9467 var = consdata->vars[0];
9468 val = consdata->vals[0];
9469 assert(!SCIPisZero(scip, val));
9470 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9471 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9472 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9473 SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9474
9475 /* fix variable */
9476 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9477 if( infeasible )
9478 {
9479 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9480 *cutoff = TRUE;
9481 return SCIP_OKAY;
9482 }
9483 if( fixed )
9484 (*nfixedvars)++;
9485
9486 /* disable constraint */
9487 SCIP_CALL( SCIPdelCons(scip, cons) );
9488 if( !consdata->upgraded )
9489 (*ndelconss)++;
9490
9491 return SCIP_OKAY;
9492}
9493
9494/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9495static
9497 SCIP* scip, /**< SCIP data structure */
9498 SCIP_CONS* cons, /**< linear constraint */
9499 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9500 int* naggrvars, /**< pointer to count number of aggregated variables */
9501 int* ndelconss /**< pointer to count number of deleted constraints */
9502 )
9503{
9504 SCIP_CONSDATA* consdata;
9505 SCIP_Bool infeasible;
9506 SCIP_Bool redundant;
9507 SCIP_Bool aggregated;
9508
9509 assert(scip != NULL);
9510 assert(cons != NULL);
9511 assert(cutoff != NULL);
9512 assert(naggrvars != NULL);
9513 assert(ndelconss != NULL);
9514
9515 consdata = SCIPconsGetData(cons);
9516 assert(consdata != NULL);
9517 assert(consdata->nvars == 2);
9518 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9519
9520 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9521 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9522 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9523
9524 /* aggregate the equality */
9525 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9526 consdata->rhs, &infeasible, &redundant, &aggregated) );
9527
9528 /* check for infeasibility of aggregation */
9529 if( infeasible )
9530 {
9531 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9532 *cutoff = TRUE;
9533 return SCIP_OKAY;
9534 }
9535
9536 /* count the aggregation */
9537 if( aggregated )
9538 (*naggrvars)++;
9539
9540 /* delete the constraint, if it is redundant */
9541 if( redundant )
9542 {
9543 SCIP_CALL( SCIPdelCons(scip, cons) );
9544
9545 if( !consdata->upgraded )
9546 (*ndelconss)++;
9547 }
9548
9549 return SCIP_OKAY;
9550}
9551
9552/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9553static
9555 SCIP* scip, /**< SCIP data structure */
9556 SCIP_CONSDATA* consdata, /**< linear constraint data */
9557 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9558 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9559 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9560 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9561 )
9562{
9563 SCIP_Real slackvarlb;
9564 SCIP_Real slackvarub;
9565
9566 assert(scip != NULL);
9567 assert(consdata != NULL);
9568 assert(newlhs != NULL);
9569 assert(newrhs != NULL);
9570 assert(!SCIPisInfinity(scip, -consdata->lhs));
9571 assert(!SCIPisInfinity(scip, consdata->rhs));
9572
9573 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9574 slackvarub = SCIPvarGetUbGlobal(slackvar);
9575 if( slackcoef > 0.0 )
9576 {
9577 if( SCIPisInfinity(scip, -slackvarlb) )
9578 *newrhs = SCIPinfinity(scip);
9579 else
9580 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9581 if( SCIPisInfinity(scip, slackvarub) )
9582 *newlhs = -SCIPinfinity(scip);
9583 else
9584 *newlhs = consdata->lhs - slackcoef * slackvarub;
9585 }
9586 else
9587 {
9588 if( SCIPisInfinity(scip, -slackvarlb) )
9589 *newlhs = -SCIPinfinity(scip);
9590 else
9591 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9592 if( SCIPisInfinity(scip, slackvarub) )
9593 *newrhs = SCIPinfinity(scip);
9594 else
9595 *newrhs = consdata->lhs - slackcoef * slackvarub;
9596 }
9597 assert(SCIPisLE(scip, *newlhs, *newrhs));
9598}
9599
9600/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9601 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9602 * is implicitly integral by this constraint
9603 *
9604 * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9605 * can help.
9606 */
9607static
9609 SCIP* scip, /**< SCIP data structure */
9610 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9611 SCIP_CONS* cons, /**< linear constraint */
9612 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9613 int* naggrvars, /**< pointer to count number of aggregated variables */
9614 int* ndelconss, /**< pointer to count number of deleted constraints */
9615 int* nchgvartypes /**< pointer to count number of changed variable types */
9616 )
9617{
9618 SCIP_CONSDATA* consdata;
9619 SCIP_VAR** vars;
9620 SCIP_Real* vals;
9621 SCIP_VARTYPE bestslacktype;
9622 SCIP_VARTYPE slacktype;
9623 SCIP_Real lhs;
9624 SCIP_Real rhs;
9625 SCIP_Real bestslackdomrng;
9626 SCIP_Real minabsval;
9627 SCIP_Real maxabsval;
9628 SCIP_Bool bestremovescons;
9629 SCIP_Bool coefszeroone;
9630 SCIP_Bool coefsintegral;
9631 SCIP_Bool varsintegral;
9632 SCIP_Bool infeasible;
9633 SCIP_Bool samevar;
9634 int supinf; /* counter for infinite contributions to the supremum of a possible
9635 * multi-aggregation
9636 */
9637 int infinf; /* counter for infinite contributions to the infimum of a possible
9638 * multi-aggregation
9639 */
9640 int maxnlocksstay;
9641 int maxnlocksremove;
9642 int bestslackpos;
9643 int bestnlocks;
9644 int ncontvars;
9645 int contvarpos;
9646 int nintvars;
9647 int nimplvars;
9648 int intvarpos;
9649 int v;
9650
9651 assert(scip != NULL);
9652 assert(cons != NULL);
9653 assert(cutoff != NULL);
9654 assert(naggrvars != NULL);
9655
9656 consdata = SCIPconsGetData(cons);
9657 assert(consdata != NULL);
9658 assert(consdata->nvars > 2);
9659 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9660
9661 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9662
9663 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9664 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9665 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9666 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9667 */
9668 lhs = consdata->lhs;
9669 rhs = consdata->rhs;
9670 maxnlocksstay = 0;
9671 if( consdata->nvars == 3 )
9672 {
9673 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9674 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9675 */
9676 maxnlocksremove = 3;
9677 }
9678 else if( consdata->nvars == 4 )
9679 {
9680 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9681 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9682 */
9683 maxnlocksremove = 2;
9684 }
9685 else
9686 {
9687 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9688 maxnlocksremove = 1;
9689 }
9690
9691 /* the locks on this constraint can be ignored */
9692 if( SCIPconsIsChecked(cons) )
9693 {
9694 if( !SCIPisInfinity(scip, -lhs) )
9695 {
9696 maxnlocksstay++;
9697 maxnlocksremove++;
9698 }
9699 if( !SCIPisInfinity(scip, rhs) )
9700 {
9701 maxnlocksstay++;
9702 maxnlocksremove++;
9703 }
9704 }
9705
9706 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9707 vars = consdata->vars;
9708 vals = consdata->vals;
9709 bestslackpos = -1;
9710 bestslacktype = SCIP_VARTYPE_BINARY;
9711 bestnlocks = INT_MAX;
9712 bestremovescons = FALSE;
9713 bestslackdomrng = 0.0;
9714 coefszeroone = TRUE;
9715 coefsintegral = TRUE;
9716 varsintegral = TRUE;
9717 ncontvars = 0;
9718 contvarpos = -1;
9719 nintvars = 0;
9720 nimplvars = 0;
9721 intvarpos = -1;
9722 minabsval = SCIPinfinity(scip);
9723 maxabsval = -1.0;
9724 for( v = 0; v < consdata->nvars; ++v )
9725 {
9726 SCIP_VAR* var;
9727 SCIP_Real val;
9728 SCIP_Real absval;
9729 SCIP_Real varlb;
9730 SCIP_Real varub;
9731 SCIP_Bool iscont;
9732 int nlocks;
9733
9734 assert(vars != NULL);
9735 assert(vals != NULL);
9736
9737 var = vars[v];
9738 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9740 varlb = SCIPvarGetLbGlobal(var);
9741 varub = SCIPvarGetUbGlobal(var);
9742
9743 val = vals[v];
9744 absval = REALABS(val);
9745 assert(SCIPisPositive(scip, absval));
9746
9747 /* calculate minimal and maximal absolute value */
9748 if( absval < minabsval )
9749 minabsval = absval;
9750 if( absval > maxabsval )
9751 maxabsval = absval;
9752
9753 /*TODO: why exit here when implied integrality can still be derived?!*/
9754 /* do not try to multi aggregate, when numerical bad */
9755 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9756 return SCIP_OKAY;
9757
9758 slacktype = SCIPvarGetType(var);
9759 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9760 coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9761 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9762 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9763
9764 /* update candidates for continuous -> implint and integer -> implint conversion */
9765 if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9766 {
9767 ncontvars++;
9768 contvarpos = v;
9769 }
9770 else if( slacktype == SCIP_VARTYPE_IMPLINT )
9771 {
9772 ++nimplvars;
9773 }
9774 else if( slacktype == SCIP_VARTYPE_INTEGER )
9775 {
9776 nintvars++;
9777 intvarpos = v;
9778 }
9779
9780 /* check, if variable is already fixed or aggregated */
9781 if( !SCIPvarIsActive(var) )
9782 continue;
9783
9784 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9786
9787 if( nlocks > maxnlocksremove )
9788 continue;
9789
9790 /* check, if variable can be used as a slack variable */
9791 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9792 !SCIPdoNotMultaggrVar(scip, var) )
9793 {
9794 SCIP_Bool better;
9795 SCIP_Bool equal;
9796 SCIP_Real slackdomrng;
9797
9798 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9799 slackdomrng = SCIPinfinity(scip);
9800 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9801 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9802 return SCIP_OKAY;
9803 else
9804 {
9805 slackdomrng = (varub - varlb)*absval;
9806 assert(!SCIPisInfinity(scip, slackdomrng));
9807 }
9808 equal = FALSE;
9809 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9810 if( !better && slacktype == bestslacktype )
9811 {
9812 better = (nlocks < bestnlocks);
9813 if( nlocks == bestnlocks && !bestremovescons )
9814 {
9815 better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9816 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9817 }
9818 }
9819
9820 if( better || equal )
9821 {
9822 SCIP_Real minresactivity;
9823 SCIP_Real maxresactivity;
9824 SCIP_Real newlhs;
9825 SCIP_Real newrhs;
9826 SCIP_Bool removescons;
9827 SCIP_Bool ismintight;
9828 SCIP_Bool ismaxtight;
9829 SCIP_Bool isminsettoinfinity;
9830 SCIP_Bool ismaxsettoinfinity;
9831
9832 /* check if the constraint becomes redundant after multi-aggregation */
9833 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9834 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
9835
9836 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9837 * activity
9838 */
9839 if( !ismintight || !ismaxtight )
9840 continue;
9841
9842 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9843 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9844
9845 /* check resactivities for reliability */
9846 if( removescons )
9847 {
9848 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9849 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9850
9851 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9852 && SCIPisFeasLE(scip, newlhs, minresactivity))
9853 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9854
9855 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9856 }
9857
9858 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9859 if( conshdlrdata->multaggrremove && !removescons )
9860 continue;
9861
9862 /* prefer variables that make the constraints redundant */
9863 if( bestremovescons && !removescons )
9864 continue;
9865
9866 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9867 * other constraints
9868 */
9869 if( !removescons && nlocks > maxnlocksstay )
9870 continue;
9871
9872 better = better || (!bestremovescons && removescons);
9873 if( better )
9874 {
9875 bestslackpos = v;
9876 bestslacktype = slacktype;
9877 bestnlocks = nlocks;
9878 bestslackdomrng = slackdomrng;
9879 bestremovescons = removescons;
9880 }
9881 }
9882 }
9883 }
9884
9885 /* if all coefficients and variables are integral, the right hand side must also be integral */
9886 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9887 {
9888 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9890 *cutoff = TRUE;
9891 return SCIP_OKAY;
9892 }
9893
9894 supinf = 0;
9895 infinf = 0;
9896 samevar = FALSE;
9897
9898 /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9899 for( v = 0; v < consdata->nvars; ++v )
9900 {
9901 if( v != bestslackpos )
9902 {
9903 if( SCIPisPositive(scip, consdata->vals[v]) )
9904 {
9905 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9906 {
9907 ++supinf;
9908 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9909 {
9910 ++infinf;
9911 samevar = TRUE;
9912 }
9913 }
9914 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9915 ++infinf;
9916 }
9917 else if( SCIPisNegative(scip, consdata->vals[v]) )
9918 {
9919 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9920 {
9921 ++supinf;
9922 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9923 {
9924 ++infinf;
9925 samevar = TRUE;
9926 }
9927 }
9928 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9929 ++infinf;
9930 }
9931 }
9932 }
9933 assert(!samevar || (supinf > 0 && infinf > 0));
9934
9935 /*TODO: implint detection again terminates early here*/
9936 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9937 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9938 if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9939 {
9940 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9941 return SCIP_OKAY;
9942 }
9943
9944 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9945 * we cannot aggregate the variable, because the integrality condition would get lost
9946 * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9947 * loose the integrality condition for this variable.
9948 */
9949 if( bestslackpos >= 0
9950 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9951 || (coefsintegral && varsintegral && nimplvars == 0)) )
9952 {
9953 SCIP_VAR* slackvar;
9955 SCIP_Real slackcoef;
9956 SCIP_Real aggrconst;
9957 SCIP_Real newlhs;
9958 SCIP_Real newrhs;
9959 SCIP_Bool aggregated;
9960
9961 /* we found a slack variable that only occurs in at most one other constraint:
9962 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9963 */
9964 assert(bestslackpos < consdata->nvars);
9965
9966 /* do not multi aggregate binary variables */
9967 if( SCIPvarIsBinary(vars[bestslackpos]) )
9968 return SCIP_OKAY;
9969
9970 /* convert equality into inequality by deleting the slack variable:
9971 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9972 */
9973 slackvar = vars[bestslackpos];
9974 slackcoef = vals[bestslackpos];
9975 assert(!SCIPisZero(scip, slackcoef));
9976 aggrconst = consdata->rhs/slackcoef;
9977
9978 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9979 assert(SCIPisLE(scip, newlhs, newrhs));
9980 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9981 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9982 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9983
9984 /* allocate temporary memory */
9985 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
9986
9987 /* set up the multi-aggregation */
9988 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9989 for( v = 0; v < consdata->nvars; ++v )
9990 {
9991 scalars[v] = -consdata->vals[v]/slackcoef;
9992 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
9993 }
9994 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9995 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9996 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9997
9998 /* perform the multi-aggregation */
9999 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10000 &infeasible, &aggregated) );
10001 assert(aggregated);
10002
10003 /* free temporary memory */
10005
10006 /* check for infeasible aggregation */
10007 if( infeasible )
10008 {
10009 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10010 *cutoff = TRUE;
10011 return SCIP_OKAY;
10012 }
10013
10014 (*naggrvars)++;
10015
10016 /* delete the constraint if it became redundant */
10017 if( bestremovescons )
10018 {
10019 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10020 SCIP_CALL( SCIPdelCons(scip, cons) );
10021
10022 if( !consdata->upgraded )
10023 (*ndelconss)++;
10024 }
10025 }
10026 else if( ncontvars == 1 )
10027 {
10028 SCIP_VAR* var;
10029
10030 assert(0 <= contvarpos && contvarpos < consdata->nvars);
10031 var = vars[contvarpos];
10033
10034 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10035 {
10036 /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10037 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10038 {
10039 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10040 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10041 SCIPconsGetName(cons), SCIPvarGetName(var));
10042 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10043 (*nchgvartypes)++;
10044 if( infeasible )
10045 {
10046 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10047 *cutoff = TRUE;
10048
10049 return SCIP_OKAY;
10050 }
10051 }
10052 /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10053 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10054 else if( !SCIPdoNotAggr(scip) )
10055 {
10056 SCIP_VAR* newvar;
10057 SCIP_Real absval;
10058 char newvarname[SCIP_MAXSTRLEN];
10059 SCIP_Bool redundant;
10060 SCIP_Bool aggregated;
10061
10062 absval = REALABS(vals[contvarpos]);
10063
10064 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10065
10066 /* create new implicit variable for aggregation */
10067 SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10069
10070 /* add new variable to problem */
10071 SCIP_CALL( SCIPaddVar(scip, newvar) );
10072
10073#ifdef WITH_DEBUG_SOLUTION
10074 if( SCIPdebugIsMainscip(scip) )
10075 {
10076 SCIP_Real varval;
10077 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10078 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10079 }
10080#endif
10081
10082 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10083 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10084 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10085
10086 /* aggregate continuous and implicit variable */
10087 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10088
10089 if( infeasible )
10090 {
10091 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10092 SCIPvarGetName(var), SCIPvarGetName(newvar));
10093 *cutoff = TRUE;
10094
10095 /* release implicit variable */
10096 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10097
10098 return SCIP_OKAY;
10099 }
10100
10101 /* release implicit variable */
10102 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10103
10104 if( aggregated )
10105 (*naggrvars)++;
10106 else
10107 return SCIP_OKAY;
10108 }
10109
10110 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10111 * again
10112 */
10113 consdata->boundstightened = 0;
10114 consdata->rangedrowpropagated = 0;
10115 consdata->presolved = FALSE;
10116 }
10117 }
10118 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10119 {
10120 SCIP_VAR* var;
10121
10122 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10123 * -> we don't convert integers into implints if the row is a 0/1-row
10124 */
10125 assert(varsintegral);
10126 assert(0 <= intvarpos && intvarpos < consdata->nvars);
10127 var = vars[intvarpos];
10128 assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10129
10130 if( coefsintegral
10131 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10132 && SCIPisFeasIntegral(scip, consdata->rhs) )
10133 {
10134 /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10135 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10136 SCIPconsGetName(cons), SCIPvarGetName(var));
10137 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10138 (*nchgvartypes)++;
10139 if( infeasible )
10140 {
10141 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10142 *cutoff = TRUE;
10143
10144 return SCIP_OKAY;
10145 }
10146 }
10147 }
10148
10149 return SCIP_OKAY;
10150}
10151
10152/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10153static
10155 SCIP* scip, /**< SCIP data structure */
10156 SCIP_CONSDATA* consdata, /**< linear constraint data */
10157 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10158 * objective function */
10159 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10160 * this constraint */
10161 )
10162{
10163 SCIP_VAR** vars;
10164 SCIP_VAR* var;
10165 SCIP_Real objval;
10166 SCIP_Bool negated;
10167 int nvars;
10168 int v;
10169
10170 vars = consdata->vars;
10171 nvars = consdata->nvars;
10172
10173 assert(vars != NULL);
10174
10175 for( v = 0; v < nvars; ++v )
10176 {
10177 negated = FALSE;
10178 var = vars[v];
10179 assert(var != NULL);
10180
10181 if( SCIPvarIsNegated(var) )
10182 {
10183 negated = TRUE;
10184 var = SCIPvarGetNegatedVar(var);
10185 assert(var != NULL);
10186 }
10187
10188 objval = SCIPvarGetObj(var);
10189
10190 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10191 * function
10192 */
10193 if( SCIPisZero(scip, objval) )
10194 return FALSE;
10195 else
10196 {
10197 SCIP_Real val;
10198
10199 val = consdata->vals[v];
10200
10201 if( negated )
10202 {
10203 if( v == 0 )
10204 {
10205 /* the first variable defines the scale */
10206 (*scale) = val / -objval;
10207
10208 (*offset) += val;
10209 }
10210 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10211 (*offset) += val;
10212 else
10213 return FALSE;
10214 }
10215 else if( v == 0 )
10216 {
10217 /* the first variable defines the scale */
10218 (*scale) = val / objval;
10219 }
10220 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10221 return FALSE;
10222 }
10223 }
10224
10225 return TRUE;
10226}
10227
10228/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10229 * objective coefficients and add an objective offset
10230 */
10231static
10233 SCIP* scip, /**< SCIP data structure */
10234 SCIP_CONS* cons, /**< linear equation constraint */
10235 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10236 )
10237{
10238 SCIP_CONSDATA* consdata;
10239 SCIP_Real offset;
10240 SCIP_Real scale;
10241 SCIP_Bool applicable;
10242 int nobjvars;
10243 int nvars;
10244 int v;
10245
10246 assert(scip != NULL);
10247 assert(cons != NULL);
10248 assert(conshdlrdata != NULL);
10249
10250 consdata = SCIPconsGetData(cons);
10251 assert(consdata != NULL);
10252 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10253
10254 nvars = consdata->nvars;
10255 nobjvars = SCIPgetNObjVars(scip);
10256
10257 /* check if the linear equality constraints does not have more variables than the objective function */
10258 if( nvars > nobjvars || nvars == 0 )
10259 return SCIP_OKAY;
10260
10261 /* check for allowance of algorithm */
10262 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10263 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10264 return SCIP_OKAY;
10265
10266 offset = consdata->rhs;
10267 scale = 1.0;
10268
10269 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10270 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10271
10272 if( applicable )
10273 {
10274 SCIP_VAR** vars;
10275
10276 vars = consdata->vars;
10277 assert(vars != NULL);
10278
10279 offset /= scale;
10280
10281 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10282 SCIPconsGetName(cons), consdata->rhs, offset);
10283
10284 /* make equality a model constraint to ensure optimality in this direction */
10287
10288 /* set all objective coefficient to zero */
10289 for( v = 0; v < nvars; ++v )
10290 {
10291 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10292 }
10293
10294 /* add an objective offset */
10295 SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10296 }
10297
10298 return SCIP_OKAY;
10299}
10300
10301/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10302static
10304 SCIP* scip, /**< SCIP data structure */
10305 SCIP_CONS* cons, /**< constraint */
10306 SCIP_Real primalbound /**< feasible primal bound */
10307 )
10308{
10309 SCIP_Real cutoffbound;
10310
10311 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10312 * accepted
10313 */
10314 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10315
10316 if( cutoffbound < SCIPgetCutoffbound(scip) )
10317 {
10318 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10319
10320 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10321 }
10322 else
10323 {
10324 SCIP_CONSDATA* consdata;
10325
10326 consdata = SCIPconsGetData(cons);
10327 assert(consdata != NULL);
10328
10329 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10330 * resulted from one side
10331 */
10332 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10333 {
10334 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10335 * propagation
10336 */
10339 }
10340 }
10341
10342 return SCIP_OKAY;
10343}
10344
10345/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10346 * constraint enters the LP by setting the initial and separated flag to FALSE
10347 */
10348static
10350 SCIP* scip, /**< SCIP data structure */
10351 SCIP_CONS* cons, /**< linear constraint */
10352 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10353 )
10354{
10355 SCIP_CONSDATA* consdata;
10356 SCIP_Real offset;
10357 SCIP_Real scale;
10358 SCIP_Bool applicable;
10359 int nobjvars;
10360 int nvars;
10361
10362 assert(scip != NULL);
10363 assert(cons != NULL);
10364 assert(conshdlrdata != NULL);
10365
10366 consdata = SCIPconsGetData(cons);
10367 assert(consdata != NULL);
10368
10369 /* ignore equalities since these are covered by the method checkPartialObjective() */
10370 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10371 return SCIP_OKAY;
10372
10373 nvars = consdata->nvars;
10374 nobjvars = SCIPgetNObjVars(scip);
10375
10376 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10377 * initial and/or separated flag is set to FALSE
10378 */
10379 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10380 return SCIP_OKAY;
10381
10382 offset = 0.0;
10383 scale = 1.0;
10384
10385 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10386 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10387 */
10388 if( nobjvars == 0 )
10389 return SCIP_OKAY;
10390
10391 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10392 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10393
10394 if( applicable )
10395 {
10396 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10397 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10398
10399 assert(scale != 0.0);
10400
10401 if( scale > 0.0 )
10402 {
10403 if( conshdlrdata->detectcutoffbound && rhsfinite )
10404 {
10405 SCIP_Real primalbound;
10406
10407 primalbound = (consdata->rhs - offset) / scale;
10408
10409 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10410 SCIPconsGetName(cons), primalbound);
10411
10412 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10413 }
10414
10415 if( conshdlrdata->detectlowerbound && lhsfinite )
10416 {
10417 SCIP_Real lowerbound;
10418
10419 lowerbound = (consdata->lhs - offset) / scale;
10420
10421 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10422 SCIPconsGetName(cons), lowerbound);
10423
10425 }
10426
10427 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10428 (conshdlrdata->detectlowerbound && !rhsfinite) )
10429 {
10430 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10433 }
10434 }
10435 else
10436 {
10437 if( conshdlrdata->detectlowerbound && rhsfinite )
10438 {
10439 SCIP_Real lowerbound;
10440
10441 lowerbound = (consdata->rhs - offset) / scale;
10442
10443 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10444 SCIPconsGetName(cons), lowerbound);
10445
10447 }
10448
10449 if( conshdlrdata->detectcutoffbound && lhsfinite )
10450 {
10451 SCIP_Real primalbound;
10452
10453 primalbound = (consdata->lhs - offset) / scale;
10454
10455 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10456 SCIPconsGetName(cons), primalbound);
10457
10458 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10459 }
10460
10461 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10462 (conshdlrdata->detectlowerbound && !lhsfinite) )
10463 {
10464 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10467 }
10468 }
10469 }
10470
10471 return SCIP_OKAY;
10472}
10473
10474/** converts special equalities */
10475static
10477 SCIP* scip, /**< SCIP data structure */
10478 SCIP_CONS* cons, /**< linear constraint */
10479 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10480 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10481 int* nfixedvars, /**< pointer to count number of fixed variables */
10482 int* naggrvars, /**< pointer to count number of aggregated variables */
10483 int* ndelconss, /**< pointer to count number of deleted constraints */
10484 int* nchgvartypes /**< pointer to count number of changed variable types */
10485 )
10486{
10487 SCIP_CONSDATA* consdata;
10488
10489 assert(scip != NULL);
10490 assert(cons != NULL);
10491 assert(conshdlrdata != NULL);
10492 assert(cutoff != NULL);
10493 assert(nfixedvars != NULL);
10494 assert(naggrvars != NULL);
10495 assert(ndelconss != NULL);
10496
10497 consdata = SCIPconsGetData(cons);
10498 assert(consdata != NULL);
10499 assert(consdata->removedfixings);
10500
10501 /* do nothing on inequalities */
10502 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10503 return SCIP_OKAY;
10504
10505 /* depending on the number of variables, call a special conversion method */
10506 if( consdata->nvars == 1 )
10507 {
10508 /* fix variable */
10509 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10510 }
10511 else if( consdata->nvars == 2 )
10512 {
10513 /* aggregate one of the variables */
10514 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10515 }
10516 else
10517 {
10518 /* check if the equality is part of the objective function */
10519 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10520
10521 /* try to multi-aggregate one of the variables */
10522 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss, nchgvartypes) );
10523 }
10524
10525 return SCIP_OKAY;
10526}
10527
10528/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10529 * integral
10530 */
10531static
10533 SCIP* scip, /**< SCIP data structure */
10534 SCIP_CONSDATA* consdata, /**< linear constraint */
10535 int pos, /**< position of variable to be left out */
10536 SCIP_Real val /**< value to divide the coefficients by */
10537 )
10538{
10539 int v;
10540
10541 assert(scip != NULL);
10542 assert(consdata != NULL);
10543 assert(0 <= pos && pos < consdata->nvars);
10544
10545 for( v = 0; v < consdata->nvars; ++v )
10546 {
10547 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10548 return FALSE;
10549 }
10550
10551 return TRUE;
10552}
10553
10554/** check if \f$lhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$,
10555 * check if \f$rhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$
10556 */
10557static
10559 SCIP* scip, /**< SCIP data structure */
10560 SCIP_Real side, /**< lhs or rhs */
10561 SCIP_Real val, /**< coefficient */
10562 SCIP_Real minresactivity, /**< minimal residual activity */
10563 SCIP_Real maxresactivity, /**< maximal residual activity */
10564 SCIP_Real* minval, /**< pointer to store calculated minval */
10565 SCIP_Real* maxval /**< pointer to store calculated maxval */
10566 )
10567{
10568 assert(scip != NULL);
10569 assert(minval != NULL);
10570 assert(maxval != NULL);
10571
10572 if( val > 0.0 )
10573 {
10574 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10575 *minval = -maxresactivity;
10576 else
10577 *minval = (side - maxresactivity)/val;
10578
10579 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10580 *maxval = -minresactivity;
10581 else
10582 *maxval = (side - minresactivity)/val;
10583 }
10584 else
10585 {
10586 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10587 *minval = minresactivity;
10588 else
10589 *minval = (side - minresactivity)/val;
10590
10591 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10592 *maxval = maxresactivity;
10593 else
10594 *maxval = (side - maxresactivity)/val;
10595 }
10596}
10597
10598
10599/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10600 * linear inequality
10601 */
10602static
10604 SCIP* scip, /**< SCIP data structure */
10605 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10606 SCIP_CONS* cons, /**< linear constraint */
10607 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10608 int* nfixedvars, /**< pointer to count number of fixed variables */
10609 int* naggrvars, /**< pointer to count number of aggregated variables */
10610 int* ndelconss, /**< pointer to count number of deleted constraints */
10611 int* nchgvartypes /**< pointer to count number of changed variable types */
10612 )
10613{
10614 SCIP_CONSDATA* consdata;
10615 SCIP_Bool lhsexists;
10616 SCIP_Bool rhsexists;
10617 SCIP_Bool bestisint;
10618 SCIP_Bool bestislhs;
10619 SCIP_Real minabsval;
10620 SCIP_Real maxabsval;
10621 int bestpos;
10622 int i;
10623 int maxotherlocks;
10624
10625 assert(scip != NULL);
10626 assert(cons != NULL);
10627 assert(cutoff != NULL);
10628 assert(nfixedvars != NULL);
10629 assert(naggrvars != NULL);
10630 assert(ndelconss != NULL);
10631
10632 /* only process checked constraints (for which the locks are increased);
10633 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10634 * dualfix presolver
10635 */
10636 if( !SCIPconsIsChecked(cons) )
10637 return SCIP_OKAY;
10638
10639 consdata = SCIPconsGetData(cons);
10640 assert(consdata != NULL);
10641
10642 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10643 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10644
10645 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10646 * can use it safely for aggregation and break the search loop
10647 */
10648 bestpos = -1;
10649 bestisint = TRUE;
10650 bestislhs = FALSE;
10651
10652 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10653 * everything else would produce fill-in. Exceptions:
10654 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10655 * produced.
10656 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10657 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10658 * six nonzeros (two variables per substitution).
10659 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10660 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10661 * six nonzeros (three variables per substitution). God exists!
10662 */
10663 if( consdata->nvars <= 2 )
10664 maxotherlocks = INT_MAX;
10665 else if( consdata->nvars == 3 )
10666 maxotherlocks = 3;
10667 else if( consdata->nvars == 4 )
10668 maxotherlocks = 2;
10669 else
10670 maxotherlocks = 1;
10671
10672 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10673 if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10674 maxotherlocks++;
10675
10676 minabsval = SCIPinfinity(scip);
10677 maxabsval = -1.0;
10678 for( i = 0; i < consdata->nvars && bestisint; ++i )
10679 {
10680 SCIP_VAR* var;
10681 SCIP_Bool isint;
10682 SCIP_Real val;
10683 SCIP_Real absval;
10684 SCIP_Real obj;
10685 SCIP_Real lb;
10686 SCIP_Real ub;
10687 SCIP_Bool agglhs;
10688 SCIP_Bool aggrhs;
10689
10690 val = consdata->vals[i];
10691 absval = REALABS(val);
10692
10693 /* calculate minimal and maximal absolute value */
10694 if( absval < minabsval )
10695 minabsval = absval;
10696 if( absval > maxabsval )
10697 maxabsval = absval;
10698
10699 /* do not try to multi aggregate, when numerical bad */
10700 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10701 return SCIP_OKAY;
10702
10703 var = consdata->vars[i];
10705
10706 /* if we already found a candidate, skip integers */
10707 if( bestpos >= 0 && isint )
10708 continue;
10709
10710 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10711 * active, fixed, or single-aggregated with another binary variable
10712 */
10713 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10714 continue;
10715
10716 if ( SCIPdoNotMultaggrVar(scip, var) )
10717 continue;
10718
10719 val = consdata->vals[i];
10720 obj = SCIPvarGetObj(var);
10721 lb = SCIPvarGetLbGlobal(var);
10722 ub = SCIPvarGetUbGlobal(var);
10723
10724 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10725 *
10726 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10727 * - constraint is the only one that forbids fixing the variable to its lower bound
10728 * - fix x_i to the smallest value for this constraint: x_i := lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
10729 *
10730 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10731 * - constraint is the only one that forbids fixing the variable to its upper bound
10732 * - fix x_i to the largest value for this constraint: x_i := lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
10733 *
10734 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10735 * - constraint is the only one that forbids fixing the variable to its upper bound
10736 * - fix x_i to the largest value for this constraint: x_i := rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
10737 *
10738 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10739 * - constraint is the only one that forbids fixing the variable to its lower bound
10740 * - fix x_i to the smallest value for this constraint: x_i := rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
10741 *
10742 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10743 * of all x_j
10744 * furthermore: we only want to apply this, if no fill-in will be produced
10745 */
10746 agglhs = lhsexists
10747 && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10748 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10749 || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10750 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10751 aggrhs = rhsexists
10752 && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10753 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10754 || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10755 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10756 if( agglhs || aggrhs )
10757 {
10758 SCIP_Real minresactivity;
10759 SCIP_Real maxresactivity;
10760 SCIP_Real minval;
10761 SCIP_Real maxval;
10762 SCIP_Bool ismintight;
10763 SCIP_Bool ismaxtight;
10764 SCIP_Bool isminsettoinfinity;
10765 SCIP_Bool ismaxsettoinfinity;
10766
10767 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10768 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10769 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
10770 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10771
10772 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10773 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10774 * This is needed, because we do not want to rely on relaxed finite resactivities.
10775 */
10776 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
10777
10778 if( agglhs )
10779 {
10780 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10781 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10782
10783 assert(SCIPisLE(scip, minval, maxval));
10784 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
10785 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
10786 {
10787 SCIP_Real oldmaxresactivity;
10788 SCIP_Real oldminresactivity;
10789 SCIP_Bool recalculated;
10790
10791 recalculated = FALSE;
10792 oldmaxresactivity = maxresactivity;
10793 oldminresactivity = minresactivity;
10794
10795 /* check minresactivity for reliability */
10796 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10797 {
10798 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10799 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10800 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10801 }
10802
10803 /* check maxresactivity for reliability */
10804 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10805 {
10806 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10807 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10808 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10809 }
10810
10811 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10812 if( recalculated )
10813 {
10814 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10815
10816 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10817 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10818
10819 assert(SCIPisLE(scip, minval, maxval));
10820 }
10821
10822 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10823 {
10824 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10825 * in the multi-aggregation
10826 */
10827 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10828 {
10829 bestpos = i;
10830 bestisint = isint;
10831 bestislhs = TRUE;
10832 continue; /* no need to also look at the right hand side */
10833 }
10834 }
10835 }
10836 }
10837
10838 if( aggrhs )
10839 {
10840 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10841 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10842
10843 assert(SCIPisLE(scip,minval,maxval));
10844 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
10845 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
10846 {
10847 SCIP_Real oldmaxresactivity;
10848 SCIP_Real oldminresactivity;
10849 SCIP_Bool recalculated;
10850
10851 recalculated = FALSE;
10852 oldmaxresactivity = maxresactivity;
10853 oldminresactivity = minresactivity;
10854
10855 /* check minresactivity for reliability */
10856 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10857 {
10858 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10859 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10860 }
10861
10862 /* check maxresactivity for reliability */
10863 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10864 {
10865 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10866 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10867 }
10868
10869 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10870 if( recalculated )
10871 {
10872 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10873 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10874 assert(SCIPisLE(scip,minval,maxval));
10875 }
10876
10877 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10878 {
10879 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10880 * in the multi-aggregation
10881 */
10882 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10883 {
10884 bestpos = i;
10885 bestisint = isint;
10886 bestislhs = FALSE;
10887 }
10888 }
10889 }
10890 }
10891 }
10892 }
10893
10894 if( bestpos >= 0 )
10895 {
10896 SCIP_VAR** aggrvars;
10897 SCIP_Real* aggrcoefs;
10898 SCIP_Real aggrconst;
10899 SCIP_VAR* bestvar;
10900 SCIP_Real bestval;
10901 int naggrs;
10902 int j;
10903 SCIP_Bool infeasible;
10904 SCIP_Bool aggregated;
10905 SCIP_Bool samevar;
10906 int supinf; /* counter for infinite contributions to the supremum of a possible
10907 * multi-aggregation
10908 */
10909 int infinf; /* counter for infinite contributions to the infimum of a possible
10910 * multi-aggregation
10911 */
10912
10913 assert(!bestislhs || lhsexists);
10914 assert(bestislhs || rhsexists);
10915
10916 bestvar = consdata->vars[bestpos];
10917 bestval = consdata->vals[bestpos];
10918 assert(bestisint ==
10920
10921 /* allocate temporary memory */
10922 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10923 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10924
10925 /* set up the multi-aggregation */
10927 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10928 naggrs = 0;
10929 supinf = 0;
10930 infinf = 0;
10931 samevar = FALSE;
10932
10933 for( j = 0; j < consdata->nvars; ++j )
10934 {
10935 if( j != bestpos )
10936 {
10937 aggrvars[naggrs] = consdata->vars[j];
10938 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10939
10940 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10941
10942 /* do not try to multi aggregate, when numerical bad */
10943 if( SCIPisZero(scip, aggrcoefs[naggrs]) )
10944 {
10945 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10946
10947 /* free temporary memory */
10948 SCIPfreeBufferArray(scip, &aggrcoefs);
10949 SCIPfreeBufferArray(scip, &aggrvars);
10950
10951 return SCIP_OKAY;
10952 }
10953
10954 if( bestisint )
10955 {
10956 /* coefficient must be integral: round it to exact integral value */
10957 assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10958 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10959 }
10960
10961 if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10962 {
10963 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10964 {
10965 ++supinf;
10966 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10967 {
10968 ++infinf;
10969 samevar = TRUE;
10970 }
10971 }
10972 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10973 ++infinf;
10974 }
10975 else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
10976 {
10977 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10978 {
10979 ++supinf;
10980 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10981 {
10982 ++infinf;
10983 samevar = TRUE;
10984 }
10985 }
10986 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10987 ++infinf;
10988 }
10989
10990 naggrs++;
10991 }
10992 }
10993 assert(!samevar || (supinf > 0 && infinf > 0));
10994
10995 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
10996 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
10997 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
10998 assert(naggrs == consdata->nvars-1);
10999
11000 /* right hand side must be integral: round it to exact integral value */
11001 if( bestisint )
11002 {
11003 assert(SCIPisIntegral(scip, aggrconst));
11004 aggrconst = SCIPfloor(scip, aggrconst+0.5);
11005 }
11006
11007 aggregated = FALSE;
11008 infeasible = FALSE;
11009
11010 /* perform the multi-aggregation */
11011 if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11012 {
11013 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11014
11015 /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11016 * the implicitness might rely on the constraint and the integrality of bestvar
11017 */
11018 if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11019 {
11020 SCIP_Bool infeasiblevartypechg;
11021
11022 for( j = 0; j < naggrs; ++j)
11023 {
11024 /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11025 * lead to infeasibility
11026 */
11027 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT )
11028 {
11029 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
11030 (*nchgvartypes)++;
11031 assert(!infeasiblevartypechg);
11032 }
11033 }
11034 }
11035 }
11036 else
11037 {
11038 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11039 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11040 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11041 }
11042 /* free temporary memory */
11043 SCIPfreeBufferArray(scip, &aggrcoefs);
11044 SCIPfreeBufferArray(scip, &aggrvars);
11045
11046 /* check for infeasible aggregation */
11047 if( infeasible )
11048 {
11049 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11050 *cutoff = TRUE;
11051 return SCIP_OKAY;
11052 }
11053
11054 /* delete the constraint, if the aggregation was successful */
11055 if( aggregated )
11056 {
11057 SCIP_CALL( SCIPdelCons(scip, cons) );
11058
11059 if( !consdata->upgraded )
11060 (*ndelconss)++;
11061 (*naggrvars)++;
11062 }
11063 else
11064 {
11065 SCIPdebugMsg(scip, "aggregation non successful!\n");
11066 }
11067 }
11068
11069 return SCIP_OKAY;
11070}
11071
11072#define BINWEIGHT 1
11073#define INTWEIGHT 4
11074#define CONTWEIGHT 8
11075
11076/** gets weight for variable in a "weighted number of variables" sum */
11077static
11079 SCIP_VAR* var /**< variable to get weight for */
11080 )
11081{
11082 switch( SCIPvarGetType(var) )
11083 {
11085 return BINWEIGHT;
11088 return INTWEIGHT;
11090 return CONTWEIGHT;
11091 default:
11092 SCIPerrorMessage("invalid variable type\n");
11093 SCIPABORT();
11094 return 0; /*lint !e527*/
11095 }
11096}
11097
11098/** tries to aggregate variables in equations a^Tx = lhs
11099 * in case there are at most two binary variables with an odd coefficient and all other
11100 * variables are not continuous and have an even coefficient then:
11101 * - exactly one odd binary variables
11102 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11103 * - lhs is odd -> y = 1
11104 * - lhs is even -> y = 0
11105 * - exactly two odd binary variables
11106 * aggregate the two binary variables with odd coefficient
11107 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11108 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11109 */
11110static
11112 SCIP* scip, /**< SCIP data structure */
11113 SCIP_CONS* cons, /**< linear constraint */
11114 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11115 int* nfixedvars, /**< pointer to count number of fixed variables */
11116 int* naggrvars /**< pointer to count number of aggregated variables */
11117 )
11118{ /*lint --e{715}*/
11119 SCIP_CONSDATA* consdata;
11120 SCIP_Bool success;
11121
11122 assert( scip != NULL );
11123 assert( cons != NULL );
11124
11125 consdata = SCIPconsGetData(cons);
11126 assert( consdata != NULL );
11127
11128 /* check if the linear constraint is an equation with integral right hand side */
11129 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11130 return SCIP_OKAY;
11131
11132 /* try to fix and aggregated variables until nothing is possible anymore */
11133 do
11134 {
11135 int v;
11136 int nvars;
11137 SCIP_VAR** vars;
11138 SCIP_Real* vals;
11139 SCIP_Real lhs;
11140 SCIP_Bool lhsodd;
11141
11142 SCIP_Bool infeasible;
11143 SCIP_Bool fixed;
11144 SCIP_Bool aggregated;
11145 SCIP_Bool redundant;
11146
11147 SCIP_VAR* var1;
11148 SCIP_VAR* var2;
11149 int noddvars;
11150
11151 success = FALSE;
11152
11153 lhs = consdata->lhs;
11154 vars = consdata->vars;
11155 vals = consdata->vals;
11156 nvars = consdata->nvars;
11157
11158 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11159
11160 var1 = NULL;
11161 var2 = NULL;
11162 noddvars = 0;
11163
11164 /* search for binary variables with an odd coefficient */
11165 for( v = 0; v < nvars && noddvars < 3; ++v )
11166 {
11167 SCIP_Longint val;
11168
11169 /* all coefficients and variables have to be integral */
11170 if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11171 return SCIP_OKAY;
11172
11173 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11174 if( val % 2 != 0 )
11175 {
11176 /* the odd values have to belong to binary variables */
11177 if( !SCIPvarIsBinary(vars[v]) )
11178 return SCIP_OKAY;
11179
11180 if( noddvars == 0 )
11181 var1 = vars[v];
11182 else
11183 var2 = vars[v];
11184
11185 noddvars++;
11186 }
11187 }
11188
11189 /* check lhs is odd or even */
11190 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11191
11192 if( noddvars == 1 )
11193 {
11194 assert( var1 != NULL );
11195
11196 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11197 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11198
11199 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11200
11201 /* check for infeasibility of fixing */
11202 if( infeasible )
11203 {
11204 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11205 *cutoff = TRUE;
11206 return SCIP_OKAY;
11207 }
11208
11209 if( fixed )
11210 {
11211 SCIPdebugMsg(scip, " -> feasible fixing\n");
11212 (*nfixedvars)++;
11213 success = TRUE;
11214 }
11215 }
11216 else if( noddvars == 2 )
11217 {
11218 assert( var1 != NULL );
11219 assert( var2 != NULL );
11220
11221 /* aggregate the two variables with odd coefficient
11222 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11223 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11224 */
11225 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11226 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11227
11228 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11229 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11230
11231 /* check for infeasibility of aggregation */
11232 if( infeasible )
11233 {
11234 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11235 *cutoff = TRUE;
11236 return SCIP_OKAY;
11237 }
11238
11239 /* count the aggregation */
11240 if( aggregated )
11241 {
11242 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11243 (*naggrvars)++;
11244 success = TRUE;
11245 }
11246 }
11247
11248 if( success )
11249 {
11250 /* apply fixings and aggregation to successfully rerun this presolving step */
11251 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11252
11253 if( infeasible )
11254 {
11255 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11256 *cutoff = TRUE;
11257 return SCIP_OKAY;
11258 }
11259
11260 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11261
11262 if( infeasible )
11263 {
11264 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11265 *cutoff = TRUE;
11266 return SCIP_OKAY;
11267 }
11268 }
11269 }
11270 while( success && consdata->nvars >= 1 );
11271
11272 return SCIP_OKAY;
11273}
11274
11275
11276
11277/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11278 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11279 * coefficients
11280 */
11281static
11283{ /*lint --e{715}*/
11284 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11285 SCIP_VARTYPE vartype1;
11286 SCIP_VARTYPE vartype2;
11287 SCIP_Real value;
11288
11289 assert(consdata != NULL);
11290 assert(0 <= ind1 && ind1 < consdata->nvars);
11291 assert(0 <= ind2 && ind2 < consdata->nvars);
11292
11293 vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11294 vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11295
11296 if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11297 {
11298 /* continuous varibles will be sorted to the back */
11299 if( vartype2 != vartype1 )
11300 return +1;
11301 /* both variables are continuous */
11302 else
11303 return 0;
11304 }
11305 /* continuous variables will be sorted to the back */
11306 else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11307 return -1;
11308
11309 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11310
11311 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11312 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11313}
11314
11315/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11316 *
11317 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11318 * then we can change this constraint to 1^Tx = 1
11319 */
11320static
11322 SCIP* scip, /**< SCIP data structure */
11323 SCIP_CONS* cons, /**< linear constraint */
11324 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11325 int* nchgsides /**< pointer to store the amount of changed sides */
11326 )
11327{
11328 SCIP_CONSDATA* consdata;
11329 SCIP_VAR** vars;
11330 SCIP_Real* vals;
11331 SCIP_Real minval;
11332 SCIP_Real secondminval;
11333 SCIP_Real maxval;
11334 SCIP_Real lhs;
11335 SCIP_Real rhs;
11336 int nvars;
11337 int v;
11338
11339 /* we must not change a modifiable constraint in any way */
11340 if( SCIPconsIsModifiable(cons) )
11341 return SCIP_OKAY;
11342
11343 if( SCIPconsIsDeleted(cons) )
11344 return SCIP_OKAY;
11345
11346 consdata = SCIPconsGetData(cons);
11347 assert(consdata != NULL);
11348
11349 nvars = consdata->nvars;
11350
11351 /* do not check empty or bound-constraints */
11352 if( nvars < 2 )
11353 return SCIP_OKAY;
11354
11355 lhs = consdata->lhs;
11356 rhs = consdata->rhs;
11357 assert(!SCIPisInfinity(scip, -lhs));
11358 assert(!SCIPisInfinity(scip, rhs));
11359 assert(!SCIPisNegative(scip, rhs));
11360
11361 /* sides must be positive and different to detect set partition */
11362 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11363 return SCIP_OKAY;
11364
11365 vals = consdata->vals;
11366 vars = consdata->vars;
11367 assert(vars != NULL);
11368 assert(vals != NULL);
11369
11370 minval = SCIP_INVALID;
11371 secondminval = SCIP_INVALID;
11372 maxval = -SCIP_INVALID;
11373
11374 for( v = nvars - 1; v >= 0; --v )
11375 {
11376 if( SCIPvarIsBinary(vars[v]) )
11377 {
11378 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11379 {
11380 secondminval = minval;
11381 minval = vals[v];
11382 }
11383 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11384 secondminval = vals[v];
11385
11386 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11387 maxval = vals[v];
11388 }
11389 else
11390 break;
11391 }
11392
11393 /* check if all variables are binary, we can choose one, and need to choose at most one */
11394 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11395 && SCIPisGT(scip, minval + secondminval, rhs) )
11396 {
11397 /* change all coefficients to 1.0 */
11398 for( v = nvars - 1; v >= 0; --v )
11399 {
11400 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11401 }
11402 (*nchgcoefs) += nvars;
11403
11404 /* replace old right and left hand side with 1.0 */
11405 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11406 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11407 (*nchgsides) += 2;
11408 }
11409
11410 return SCIP_OKAY;
11411}
11412
11413/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11414 *
11415 * for both-sided constraints only @see rangedRowSimplify() will be called
11416 *
11417 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11418 *
11419 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11420 *
11421 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11422 *
11423 * 2. We try to remove redundant fractional parts in a constraint
11424 *
11425 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11426 *
11427 * 3. We are using the greatest common divisor for further reductions
11428 *
11429 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11430 * integral
11431 */
11432static
11434 SCIP* scip, /**< SCIP data structure */
11435 SCIP_CONS* cons, /**< linear constraint */
11436 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11437 int* nchgsides, /**< pointer to store the amount of changed sides */
11438 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11439 )
11440{
11441 SCIP_CONSDATA* consdata;
11442 SCIP_VAR** vars;
11443 SCIP_Real* vals;
11444 int* perm;
11445 SCIP_Real minactsub;
11446 SCIP_Real maxactsub;
11447 SCIP_Real siderest;
11448 SCIP_Real feastol;
11449 SCIP_Real newcoef;
11450 SCIP_Real absval;
11451 SCIP_Real minact;
11452 SCIP_Real maxact;
11453 SCIP_Real side;
11454 SCIP_Real lhs;
11455 SCIP_Real rhs;
11456 SCIP_Real lb;
11457 SCIP_Real ub;
11458 SCIP_Longint restcoef;
11459 SCIP_Longint oldgcd;
11460 SCIP_Longint rest;
11461 SCIP_Longint gcd;
11462 SCIP_Bool isminsettoinfinity;
11463 SCIP_Bool ismaxsettoinfinity;
11464 SCIP_Bool ismintight;
11465 SCIP_Bool ismaxtight;
11466 SCIP_Bool allcoefintegral;
11467 SCIP_Bool onlybin;
11468 SCIP_Bool hasrhs;
11469 SCIP_Bool haslhs;
11470 int oldnchgcoefs;
11471 int oldnchgsides;
11472 int foundbin;
11473 int candpos;
11474 int candpos2;
11475 int offsetv;
11476 int nvars;
11477 int v;
11478 int w;
11479
11480 assert(scip != NULL);
11481 assert(cons != NULL);
11482 assert(nchgcoefs != NULL);
11483 assert(nchgsides != NULL);
11484
11485 *infeasible = FALSE;
11486
11487 /* we must not change a modifiable constraint in any way */
11488 if( SCIPconsIsModifiable(cons) )
11489 return SCIP_OKAY;
11490
11491 if( SCIPconsIsDeleted(cons) )
11492 return SCIP_OKAY;
11493
11494 consdata = SCIPconsGetData(cons);
11495 assert(consdata != NULL);
11496
11497 nvars = consdata->nvars;
11498
11499 /* do not check empty or bound-constraints */
11500 if( nvars <= 2 )
11501 return SCIP_OKAY;
11502
11503 /* update maximal activity delta if necessary */
11504 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11506
11507 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11508 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11509 checkMaxActivityDelta(scip, consdata);
11510
11511 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11512 * accordingly
11513 */
11514 /* can only work with valid non-infinity activities per variable */
11515 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11516 return SCIP_OKAY;
11517
11518 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11519 * but the eventsystem seems to be full
11520 */
11521 consdata->normalized = FALSE;
11522
11523 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11524 assert(nvars == consdata->nvars);
11525
11526 if( *infeasible )
11527 return SCIP_OKAY;
11528
11529 if( !consdata->normalized )
11530 return SCIP_OKAY;
11531
11532 lhs = consdata->lhs;
11533 rhs = consdata->rhs;
11534 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11535 assert(!SCIPisNegative(scip, rhs));
11536
11537 if( !SCIPisInfinity(scip, -lhs) )
11538 haslhs = TRUE;
11539 else
11540 haslhs = FALSE;
11541
11542 if( !SCIPisInfinity(scip, rhs) )
11543 hasrhs = TRUE;
11544 else
11545 hasrhs = FALSE;
11546
11547 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11548 SCIPdebug( oldnchgsides = *nchgsides; )
11549
11550 /* @todo extend both-sided simplification */
11551 if( haslhs && hasrhs )
11552 {
11553 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11554
11555 return SCIP_OKAY;
11556 }
11557 assert(haslhs != hasrhs);
11558
11559 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11560 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11561 assert(!haslhs || !SCIPisNegative(scip, lhs));
11562
11563 /* get temporary memory to store the sorted permutation */
11564 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11565
11566 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11567 * value of their coefficients
11568 */
11569 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11570
11571 /* perform sorting after permutation array */
11572 permSortConsdata(consdata, perm, nvars);
11573 consdata->indexsorted = FALSE;
11574 consdata->coefsorted = FALSE;
11575
11576 vars = consdata->vars;
11577 vals = consdata->vals;
11578 assert(vars != NULL);
11579 assert(vals != NULL);
11580 assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11581
11582 /* free temporary memory */
11583 SCIPfreeBufferArray(scip, &perm);
11584
11585 /* only check constraints with at least two non continuous variables */
11586 if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11587 return SCIP_OKAY;
11588
11589 /* do not process constraints when all coefficients are 1.0 */
11590 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11591 return SCIP_OKAY;
11592
11593 feastol = SCIPfeastol(scip);
11594
11595 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11597
11598 /* get global activities */
11599 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11600 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
11601
11602 /* cannot work with infinite activities */
11603 if( isminsettoinfinity || ismaxsettoinfinity )
11604 return SCIP_OKAY;
11605
11606 assert(ismintight);
11607 assert(ismaxtight);
11608 assert(maxact > minact);
11609 assert(!SCIPisInfinity(scip, -minact));
11610 assert(!SCIPisInfinity(scip, maxact));
11611
11612 v = 0;
11613 offsetv = -1;
11614 side = haslhs ? lhs : rhs;
11615 minactsub = minact;
11616 maxactsub = maxact;
11617
11618 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11619 * do not need to look at the large coefficients
11620 *
11621 * e.g. all x are binary, z are positive integer
11622 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11623 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11624 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11625 *
11626 * can be changed to
11627 *
11628 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11629 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11630 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11631 */
11632
11633 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11634 * hand side, we cannot apply the extra reduction step and need to reset v
11635 *
11636 * 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
11637 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11638 * for all i is a solution
11639 *
11640 * also redundancy of variables would not be correctly determined in such a case
11641 */
11642 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11643 {
11644 v = 1;
11645
11646 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11647 {
11648 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11649 * extra step, which might have worked
11650 */
11651 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11652 {
11653 v = 0;
11654 break;
11655 }
11656
11657 ++v;
11658 }
11659
11660 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11661 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11662 if( v == nvars )
11663 return SCIP_OKAY;
11664
11665 /* cannot work with continuous variables which have a big coefficient */
11666 if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11667 return SCIP_OKAY;
11668
11669 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11670 if( SCIPisEQ(scip, side, -vals[v]) )
11671 v = 0;
11672
11673 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11674 * reduction
11675 */
11676 if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11677 v = 0;
11678
11679 if( v > 0 )
11680 {
11681 assert(v < nvars);
11682
11683 offsetv = v - 1;
11684
11685 for( w = 0; w < v; ++w )
11686 {
11687 lb = SCIPvarGetLbGlobal(vars[w]);
11688 ub = SCIPvarGetUbGlobal(vars[w]);
11689
11690 assert(vals[w] > 0);
11691
11692 /* update residual activities */
11693 maxactsub -= ub * vals[w];
11694 minactsub -= lb * vals[w];
11695 assert(maxactsub > minactsub);
11696 }
11697 }
11698 }
11699
11700 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11701 *
11702 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11703 *
11704 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11705 * to
11706 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11707 */
11708 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11709 {
11710 SCIP_Bool redundant = FALSE;
11711 SCIP_Bool numericsok;
11712 SCIP_Bool rredundant;
11713 SCIP_Bool lredundant;
11714
11715 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11716 assert(gcd >= 1);
11717
11718 if( v == 0 )
11719 {
11720 lb = SCIPvarGetLbGlobal(vars[0]);
11721 ub = SCIPvarGetUbGlobal(vars[0]);
11722
11723 /* update residual activities */
11724 if( vals[0] > 0 )
11725 {
11726 maxactsub -= ub * vals[0];
11727 minactsub -= lb * vals[0];
11728 }
11729 else
11730 {
11731 maxactsub -= lb * vals[0];
11732 minactsub -= ub * vals[0];
11733 }
11734 assert(maxactsub > minactsub);
11735 ++v;
11736 }
11737
11738 siderest = -SCIP_INVALID;
11739 allcoefintegral = TRUE;
11740
11741 /* check if some variables always fit into the given constraint */
11742 for( ; v < nvars - 1; ++v )
11743 {
11744 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11745 break;
11746
11747 if( !SCIPisIntegral(scip, vals[v]) )
11748 {
11749 allcoefintegral = FALSE;
11750 break;
11751 }
11752
11753 /* calculate greatest common divisor for all general and binary variables */
11754 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11755
11756 if( gcd == 1 )
11757 break;
11758
11759 lb = SCIPvarGetLbGlobal(vars[v]);
11760 ub = SCIPvarGetUbGlobal(vars[v]);
11761
11762 assert(!SCIPisInfinity(scip, -lb));
11763 assert(!SCIPisInfinity(scip, ub));
11764
11765 /* update residual activities */
11766 if( vals[v] > 0 )
11767 {
11768 maxactsub -= ub * vals[v];
11769 minactsub -= lb * vals[v];
11770 }
11771 else
11772 {
11773 maxactsub -= lb * vals[v];
11774 minactsub -= ub * vals[v];
11775 }
11776 assert(SCIPisGE(scip, maxactsub, minactsub));
11777
11778 if( hasrhs )
11779 {
11780 /* determine the remainder of the right hand side and the gcd */
11781 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11782 }
11783 else
11784 {
11785 /* determine the remainder of the left hand side and the gcd */
11786 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11787 if( SCIPisZero(scip, siderest) )
11788 siderest = gcd;
11789 }
11790
11791 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11792 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11793
11794 /* early termination if the activities deceed the gcd */
11795 if( offsetv == -1 && (rredundant || lredundant) )
11796 {
11797 redundant = TRUE;
11798 break;
11799 }
11800 }
11801 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11802
11803 if( !redundant )
11804 {
11805 if( hasrhs )
11806 {
11807 /* determine the remainder of the right hand side and the gcd */
11808 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11809 }
11810 else
11811 {
11812 /* determine the remainder of the left hand side and the gcd */
11813 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11814 if( SCIPisZero(scip, siderest) )
11815 siderest = gcd;
11816 }
11817 }
11818 else
11819 ++v;
11820
11821 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",
11822 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11823
11824 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11825 * reasonable absolute values */
11826 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11827 REALABS(minactsub) < MAXACTVAL;
11828
11829 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11830 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11831
11832 /* check if we can remove redundant variables */
11833 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11834 {
11835 SCIP_Real oldcoef;
11836
11837 /* double check the redundancy */
11838#ifndef NDEBUG
11839 SCIP_Real tmpminactsub = 0.0;
11840 SCIP_Real tmpmaxactsub = 0.0;
11841
11842 /* recompute residual activities */
11843 for( w = v; w < nvars; ++w )
11844 {
11845 lb = SCIPvarGetLbGlobal(vars[w]);
11846 ub = SCIPvarGetUbGlobal(vars[w]);
11847
11848 assert(!SCIPisInfinity(scip, -lb));
11849 assert(!SCIPisInfinity(scip, ub));
11850
11851 /* update residual activities */
11852 if( vals[w] > 0 )
11853 {
11854 tmpmaxactsub += ub * vals[w];
11855 tmpminactsub += lb * vals[w];
11856 }
11857 else
11858 {
11859 tmpmaxactsub += lb * vals[w];
11860 tmpminactsub += ub * vals[w];
11861 }
11862 assert(tmpmaxactsub >= tmpminactsub);
11863 }
11864
11865 if( hasrhs )
11866 {
11867 assert(offsetv == -1);
11868
11869 /* determine the remainder of the right hand side and the gcd */
11870 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11871 }
11872 else
11873 {
11874 /* determine the remainder of the left hand side and the gcd */
11875 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11876 if( SCIPisZero(scip, siderest) )
11877 siderest = gcd;
11878 }
11879
11880 /* is the redundancy really fulfilled */
11881 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11882 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11883#endif
11884
11885 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11886 nvars - v, SCIPconsGetName(cons));
11887
11888 /* remove redundant variables */
11889 for( w = nvars - 1; w >= v; --w )
11890 {
11891 SCIP_CALL( delCoefPos(scip, cons, w) );
11892 }
11893 (*nchgcoefs) += (nvars - v);
11894
11895 assert(w >= 0);
11896
11897 oldcoef = vals[w];
11898
11899 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11900 assert(vars == consdata->vars);
11901 assert(vals == consdata->vals);
11902 assert(w < consdata->nvars);
11903
11904 if( *infeasible )
11905 return SCIP_OKAY;
11906
11907 /* compute new greatest common divisor due to normalization */
11908 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11909 assert(gcd >= 1);
11910
11911 /* update side */
11912 if( hasrhs )
11913 {
11914 /* replace old with new right hand side */
11915 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11916 rhs = consdata->rhs;
11917 }
11918 else
11919 {
11920 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11921 {
11922 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11923 lhs = consdata->lhs;
11924 }
11925 else
11926 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11927 }
11928 ++(*nchgsides);
11929
11930 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11931 assert(!haslhs || !SCIPisNegative(scip, lhs));
11932
11933 /* get new constraint data */
11934 nvars = consdata->nvars;
11935 assert(nvars > 0);
11936
11937 allcoefintegral = TRUE;
11938
11939#ifndef NDEBUG
11940 /* check integrality */
11941 for( w = offsetv + 1; w < nvars; ++w )
11942 {
11943 assert(SCIPisIntegral(scip, vals[w]));
11944 }
11945#endif
11947 }
11948
11949 /* try to find a better gcd, when having large coefficients */
11950 if( offsetv >= 0 && gcd == 1 )
11951 {
11952 /* calculate greatest common divisor for all general variables */
11953 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11954
11955 if( gcd > 1 )
11956 {
11957 gcd = -1;
11958 candpos = -1;
11959
11960 for( v = nvars - 1; v > offsetv; --v )
11961 {
11962 assert(!SCIPisZero(scip, vals[v]));
11963 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11964 break;
11965
11966 if( !SCIPisIntegral(scip, vals[v]) )
11967 {
11968 allcoefintegral = FALSE;
11969 break;
11970 }
11971
11972 oldgcd = gcd;
11973
11974 if( gcd == -1 )
11975 {
11976 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11977 assert(gcd >= 1);
11978 }
11979 else
11980 {
11981 /* calculate greatest common divisor for all general and binary variables */
11982 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11983 }
11984
11985 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11986 * can stop searching
11987 */
11988 if( gcd == 1 )
11989 {
11990 if( !SCIPvarIsBinary(vars[v]) )
11991 break;
11992
11993 /* found candidate */
11994 if( candpos == -1 )
11995 {
11996 gcd = oldgcd;
11997 candpos = v;
11998 }
11999 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12000 else
12001 break;
12002 }
12003 }
12004 assert(v > offsetv || candpos > offsetv);
12005 }
12006 else
12007 candpos = -1;
12008 }
12009 else
12010 candpos = nvars - 1;
12011
12012 /* check last coefficient for integrality */
12013 if( gcd > 1 && allcoefintegral && !redundant )
12014 {
12015 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12016 allcoefintegral = FALSE;
12017 }
12018
12019 /* check for further necessary coefficient adjustments */
12020 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12021 {
12022 assert(offsetv + 1 < nvars);
12023 assert(0 <= candpos && candpos < nvars);
12024
12025 if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12026 {
12027 SCIP_Bool notchangable = FALSE;
12028
12029#ifndef NDEBUG
12030 /* check integrality */
12031 for( w = offsetv + 1; w < nvars; ++w )
12032 {
12033 assert(SCIPisIntegral(scip, vals[w]));
12034 }
12035#endif
12036
12037 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12038 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12039 {
12040 /* determine the remainder of the side and the gcd */
12041 if( hasrhs )
12042 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12043 else
12044 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12045 assert(rest >= 0);
12046 assert(rest < gcd);
12047
12048 /* determine the remainder of the coefficient candidate and the gcd */
12049 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12050 assert(restcoef >= 1);
12051 assert(restcoef < gcd);
12052
12053 if( hasrhs )
12054 {
12055 /* calculate new coefficient */
12056 if( restcoef > rest )
12057 newcoef = vals[candpos] - restcoef + gcd;
12058 else
12059 newcoef = vals[candpos] - restcoef;
12060 }
12061 else
12062 {
12063 /* calculate new coefficient */
12064 if( rest == 0 || restcoef < rest )
12065 newcoef = vals[candpos] - restcoef;
12066 else
12067 newcoef = vals[candpos] - restcoef + gcd;
12068 }
12069
12070 /* done */
12071
12072 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12073 * another with the big coefficient was set to 1
12074 */
12075 if( hasrhs && SCIPisZero(scip, newcoef) )
12076 {
12077 notchangable = TRUE;
12078 }
12079 else if( SCIPisZero(scip, newcoef) )
12080 {
12081 /* delete old redundant coefficient */
12082 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12083 ++(*nchgcoefs);
12084 }
12085 else
12086 {
12087 /* replace old with new coefficient */
12088 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12089 ++(*nchgcoefs);
12090 }
12091 }
12092 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12093 {
12094 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12095 }
12096
12097 /* correct side and big coefficients */
12098 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12099 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12100 {
12101 if( haslhs )
12102 {
12103 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12104
12105 SCIP_CALL( chgLhs(scip, cons, newcoef) );
12106 ++(*nchgsides);
12107 }
12108 else
12109 {
12110 assert(hasrhs);
12111 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12112
12113 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12114 ++(*nchgsides);
12115 }
12116
12117 /* correct coefficients up front */
12118 for( w = offsetv; w >= 0; --w )
12119 {
12120 assert(vals[w] > 0);
12121
12122 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12123 }
12124 (*nchgcoefs) += (offsetv + 1);
12125 }
12126
12127 if( !notchangable )
12128 {
12129 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12130 assert(vars == consdata->vars);
12131 assert(vals == consdata->vals);
12132
12133 if( *infeasible )
12134 return SCIP_OKAY;
12135
12136 /* get new constraint data */
12137 nvars = consdata->nvars;
12138 assert(nvars >= 2);
12139
12141
12142 lhs = consdata->lhs;
12143 rhs = consdata->rhs;
12144 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12145 assert(!haslhs || !SCIPisNegative(scip, lhs));
12146 }
12147 }
12148 }
12149 }
12150
12151 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12152 /* no continuous variables are left over */
12153 if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12154 return SCIP_OKAY;
12155
12156 onlybin = TRUE;
12157 allcoefintegral = TRUE;
12158 /* check if all variables are of binary type */
12159 for( v = nvars - 1; v >= 0; --v )
12160 {
12161 if( !SCIPvarIsBinary(vars[v]) )
12162 onlybin = FALSE;
12163 if( !SCIPisIntegral(scip, vals[v]) )
12164 allcoefintegral = FALSE;
12165 }
12166
12167 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12168 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12169 *
12170 * @todo there are some steps missing ....
12171 */
12172 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12173 {
12174 SCIP_Real val;
12175 SCIP_Real newval;
12176 SCIP_Real frac = 0.0;
12177 SCIP_Bool found = FALSE;
12178
12179 if( hasrhs )
12180 {
12181 if( allcoefintegral )
12182 {
12183 /* replace old with new right hand side */
12184 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12185 ++(*nchgsides);
12186 }
12187 else
12188 {
12189 siderest = rhs - SCIPfloor(scip, rhs);
12190
12191 /* try to round down all non-integral coefficients */
12192 for( v = nvars - 1; v >= 0; --v )
12193 {
12194 val = vals[v];
12195
12196 /* add up all possible fractional parts */
12197 if( !SCIPisIntegral(scip, val) )
12198 {
12199 lb = SCIPvarGetLbGlobal(vars[v]);
12200 ub = SCIPvarGetUbGlobal(vars[v]);
12201
12202 /* at least one bound need to be at zero */
12203 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12204 return SCIP_OKAY;
12205
12206 /* swap bounds for 'standard' form */
12207 if( !SCIPisFeasZero(scip, lb) )
12208 {
12209 ub = lb;
12210 val *= -1;
12211 }
12212
12213 found = TRUE;
12214
12215 frac += (val - SCIPfloor(scip, val)) * ub;
12216
12217 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12218 *
12219 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12220 * x3, x4 set to 1 would be infeasible but feasible after flooring
12221 */
12222 if( SCIPisGT(scip, frac, siderest) )
12223 return SCIP_OKAY;
12224 }
12225 }
12226 assert(v == -1);
12227
12228 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12229
12230 /* round rhs and coefficients to integral values */
12231 if( found )
12232 {
12233 for( v = nvars - 1; v >= 0; --v )
12234 {
12235 val = vals[v];
12236
12237 /* add the whole fractional part */
12238 if( !SCIPisIntegral(scip, val) )
12239 {
12240 lb = SCIPvarGetLbGlobal(vars[v]);
12241
12242 if( SCIPisFeasZero(scip, lb) )
12243 newval = SCIPfloor(scip, val);
12244 else
12245 newval = SCIPceil(scip, val);
12246
12247 if( SCIPisZero(scip, newval) )
12248 {
12249 /* delete old redundant coefficient */
12250 SCIP_CALL( delCoefPos(scip, cons, v) );
12251 ++(*nchgcoefs);
12252 }
12253 else
12254 {
12255 /* replace old with new coefficient */
12256 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12257 ++(*nchgcoefs);
12258 }
12259 }
12260 }
12261 }
12262
12263 /* replace old with new right hand side */
12264 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12265 ++(*nchgsides);
12266 }
12267 }
12268 else
12269 {
12270 if( allcoefintegral )
12271 {
12272 /* replace old with new left hand side */
12273 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12274 ++(*nchgsides);
12275 }
12276 else
12277 {
12278 /* cannot floor left hand side to zero */
12279 if( SCIPisLT(scip, lhs, 1.0) )
12280 return SCIP_OKAY;
12281
12282 siderest = lhs - SCIPfloor(scip, lhs);
12283
12284 /* try to round down all non-integral coefficients */
12285 for( v = nvars - 1; v >= 0; --v )
12286 {
12287 val = vals[v];
12288
12289 /* add up all possible fractional parts */
12290 if( !SCIPisIntegral(scip, val) )
12291 {
12292 lb = SCIPvarGetLbGlobal(vars[v]);
12293 ub = SCIPvarGetUbGlobal(vars[v]);
12294
12295 /* at least one bound need to be at zero */
12296 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12297 return SCIP_OKAY;
12298
12299 /* swap bounds for 'standard' form */
12300 if( !SCIPisFeasZero(scip, lb) )
12301 {
12302 ub = lb;
12303 val *= -1;
12304 }
12305
12306 /* cannot floor to zero */
12307 if( SCIPisLT(scip, val, 1.0) )
12308 return SCIP_OKAY;
12309
12310 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12311 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12312 return SCIP_OKAY;
12313
12314 found = TRUE;
12315
12316 frac += (val - SCIPfloor(scip, val)) * ub;
12317
12318 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12319 * fractional parts of the variables, we cannot tighten the coefficients
12320 *
12321 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12322 * x2-x4 set to 1 would be feasible but not after flooring
12323 */
12324 if( SCIPisGE(scip, frac, 1 + siderest) )
12325 return SCIP_OKAY;
12326 }
12327 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12328 else
12329 return SCIP_OKAY;
12330 }
12331 assert(v == -1);
12332
12333 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12334
12335 /* round lhs and coefficients to integral values */
12336 if( found )
12337 {
12338 for( v = nvars - 1; v >= 0; --v )
12339 {
12340 val = vals[v];
12341
12342 /* add the whole fractional part */
12343 if( !SCIPisIntegral(scip, val) )
12344 {
12345 lb = SCIPvarGetLbGlobal(vars[v]);
12346
12347 if( SCIPisFeasZero(scip, lb) )
12348 newval = SCIPfloor(scip, val);
12349 else
12350 newval = SCIPceil(scip, val);
12351
12352 if( SCIPisZero(scip, newval) )
12353 {
12354 /* delete old redundant coefficient */
12355 SCIP_CALL( delCoefPos(scip, cons, v) );
12356 ++(*nchgcoefs);
12357 }
12358 else
12359 {
12360 /* replace old with new coefficient */
12361 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12362 ++(*nchgcoefs);
12363 }
12364 }
12365 }
12366 }
12367
12368 /* replace old with new left hand side */
12369 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12370 ++(*nchgsides);
12371 }
12372 }
12373
12374 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12375 assert(vars == consdata->vars);
12376 assert(vals == consdata->vals);
12377
12378 if( *infeasible )
12379 return SCIP_OKAY;
12380
12381 rhs = consdata->rhs;
12382 lhs = consdata->lhs;
12383
12384 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12385 assert(!haslhs || !SCIPisNegative(scip, lhs));
12386
12388
12389 nvars = consdata->nvars;
12390 if( nvars < 2 )
12391 return SCIP_OKAY;
12392
12393 allcoefintegral = TRUE;
12394#ifndef NDEBUG
12395 /* debug check if all coefficients are really integral */
12396 for( v = nvars - 1; v >= 0; --v )
12397 assert(SCIPisIntegral(scip, vals[v]));
12398#endif
12399 }
12400
12401 /* @todo following can also work on non integral coefficients, need more investigation */
12402 /* only check constraints with integral coefficients on all integral variables */
12403 if( !allcoefintegral )
12404 return SCIP_OKAY;
12405
12406 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12407 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12408 return SCIP_OKAY;
12409
12410 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12411 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12412 return SCIP_OKAY;
12413
12414 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12415 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12416 return SCIP_OKAY;
12417
12418 assert(nvars >= 2);
12419
12420 /* start gcd procedure for all variables */
12421 do
12422 {
12423 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12424 SCIPdebug( oldnchgsides = *nchgsides; )
12425
12426 /* stop if we have two coeffcients which are one in absolute value */
12427 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12428 return SCIP_OKAY;
12429
12430 gcd = -1;
12431
12432 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12433 * because coefficients of non-binary variables might have changed to zero */
12434 if( !onlybin )
12435 {
12436 foundbin = -1;
12437 onlybin = TRUE;
12438
12439 for( v = nvars - 1; v >= 0; --v )
12440 {
12441 assert(!SCIPisZero(scip, vals[v]));
12442 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12443
12444 if( SCIPvarIsBinary(vars[v]) )
12445 {
12446 if( foundbin == -1 )
12447 foundbin = v;
12448 continue;
12449 }
12450 else
12451 onlybin = FALSE;
12452
12453 absval = REALABS(vals[v]);
12454 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12455 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12456 */
12457 assert(SCIPisFeasIntegral(scip, absval));
12458
12459 if( gcd == -1 )
12460 {
12461 gcd = (SCIP_Longint)(absval + feastol);
12462 assert(gcd >= 1);
12463 }
12464 else
12465 {
12466 /* calculate greatest common divisor for all general variables */
12467 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12468 }
12469 if( gcd == 1 )
12470 break;
12471 }
12472 }
12473 else
12474 foundbin = nvars - 1;
12475
12476 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12477 if( gcd == 1 || foundbin == -1)
12478 return SCIP_OKAY;
12479
12480 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12481
12482 candpos = -1;
12483 candpos2 = -1;
12484
12485 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12486 * change the coefficient
12487 */
12488 for( v = foundbin; v >= 0; --v )
12489 {
12490 if( onlybin || SCIPvarIsBinary(vars[v]) )
12491 {
12492 absval = REALABS(vals[v]);
12493 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12494 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12495 */
12496 assert(SCIPisFeasIntegral(scip, absval));
12497
12498 oldgcd = gcd;
12499
12500 if( gcd == -1 )
12501 {
12502 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12503 assert(gcd >= 1);
12504 }
12505 else
12506 {
12507 /* calculate greatest common divisor for all general and binary variables */
12508 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12509 }
12510
12511 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12512 * can terminate
12513 */
12514 if( gcd == 1 )
12515 {
12516 /* found candidate */
12517 if( candpos == -1 )
12518 {
12519 gcd = oldgcd;
12520 candpos = v;
12521
12522 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12523 * the coefficient change
12524 */
12525 if( onlybin && v == foundbin - 1 )
12526 candpos2 = foundbin;
12527 }
12528 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12529 else
12530 {
12531 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12532 {
12533 assert(candpos2 == nvars - 1);
12534
12535 /* take new candidates */
12536 candpos = candpos2;
12537
12538 /* recalculate gcd from scratch */
12539 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12540 assert(gcd >= 1);
12541
12542 /* calculate greatest common divisor for all general and binary variables */
12543 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12544 if( gcd == 1 )
12545 return SCIP_OKAY;
12546 }
12547 else
12548 /* cannot determine a possible coefficient for reduction */
12549 return SCIP_OKAY;
12550 }
12551 }
12552 }
12553 }
12554 assert(gcd >= 2);
12555
12556 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12557 * further
12558 */
12559 assert(candpos >= 0 && candpos < nvars);
12560
12561 /* all variables and all coefficients are integral, so the side should be too */
12562 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12563
12564 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12565 * @see normalizeCons()
12566 */
12567 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12568 assert(!haslhs || !SCIPisNegative(scip, lhs));
12569
12570 /* determine the remainder of the side and the gcd */
12571 if( hasrhs )
12572 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12573 else
12574 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12575 assert(rest >= 0);
12576 assert(rest < gcd);
12577
12578 /* determine the remainder of the coefficient candidate and the gcd */
12579 if( vals[candpos] < 0 )
12580 {
12581 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12582 assert(restcoef <= -1);
12583 restcoef += gcd;
12584 }
12585 else
12586 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12587 assert(restcoef >= 1);
12588 assert(restcoef < gcd);
12589
12590 if( hasrhs )
12591 {
12592 if( rest > 0 )
12593 {
12594 /* replace old with new right hand side */
12595 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12596 ++(*nchgsides);
12597 }
12598
12599 /* calculate new coefficient */
12600 if( restcoef > rest )
12601 newcoef = vals[candpos] - restcoef + gcd;
12602 else
12603 newcoef = vals[candpos] - restcoef;
12604 }
12605 else
12606 {
12607 if( rest > 0 )
12608 {
12609 /* replace old with new left hand side */
12610 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12611 ++(*nchgsides);
12612 }
12613
12614 /* calculate new coefficient */
12615 if( rest == 0 || restcoef < rest )
12616 newcoef = vals[candpos] - restcoef;
12617 else
12618 newcoef = vals[candpos] - restcoef + gcd;
12619 }
12620 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12621
12622 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));
12623
12624 if( SCIPisZero(scip, newcoef) )
12625 {
12626 /* delete redundant coefficient */
12627 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12628 }
12629 else
12630 {
12631 /* replace old with new coefficient */
12632 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12633 }
12634 ++(*nchgcoefs);
12635
12636 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12637 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12638 assert(vars == consdata->vars);
12639 assert(vals == consdata->vals);
12640
12641 if( *infeasible )
12642 return SCIP_OKAY;
12643
12645
12646 rhs = consdata->rhs;
12647 lhs = consdata->lhs;
12648 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12649 assert(!haslhs || !SCIPisNegative(scip, lhs));
12650
12651 nvars = consdata->nvars;
12652
12653 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));
12654 }
12655 while( nvars >= 2 );
12656
12657 return SCIP_OKAY;
12658}
12659
12660
12661/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12662 * cons0 := a * cons0 + b * cons1,
12663 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12664 * for numerical stability, we will only accept integral a and b;
12665 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12666 * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12667 */
12668static
12670 SCIP* scip, /**< SCIP data structure */
12671 SCIP_CONS* cons0, /**< (in)equality to modify */
12672 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12673 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12674 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12675 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12676 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12677 int nvarscommon, /**< number of variables, that appear in both constraints */
12678 int commonidxweight, /**< variable weight sum of common variables */
12679 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12680 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12681 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12682 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12683 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12684 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12685 )
12686{
12687 SCIP_CONSDATA* consdata0;
12688 SCIP_CONSDATA* consdata1;
12689 SCIP_Real a;
12690 SCIP_Real b;
12691 SCIP_Real aggrcoef;
12692 SCIP_Real scalarsum;
12693 SCIP_Real bestscalarsum;
12694 SCIP_Bool betterscalarsum;
12695 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12696 int varweight;
12697 int nvars;
12698 int bestvarweight;
12699 int bestnvars;
12700 int bestv;
12701 int v;
12702 int i;
12703
12704 assert(scip != NULL);
12705 assert(cons0 != NULL);
12706 assert(cons1 != NULL);
12707 assert(commonidx0 != NULL);
12708 assert(commonidx1 != NULL);
12709 assert(diffidx0minus1 != NULL);
12710 assert(diffidx1minus0 != NULL);
12711 assert(nvarscommon >= 1);
12712 assert(commonidxweight >= nvarscommon);
12713 assert(nchgcoefs != NULL);
12714 assert(aggregated != NULL);
12715
12716 assert(SCIPconsIsActive(cons0));
12717 assert(SCIPconsIsActive(cons1));
12718
12719 *infeasible = FALSE;
12720
12721 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12722
12723 /* cons0 is an (in)equality */
12724 consdata0 = SCIPconsGetData(cons0);
12725 assert(consdata0 != NULL);
12726 assert(consdata0->nvars >= 1);
12727 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12728 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12729
12730 /* cons1 is an equality */
12731 consdata1 = SCIPconsGetData(cons1);
12732 assert(consdata1 != NULL);
12733 assert(consdata1->nvars >= 1);
12734 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12735 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12736
12737 *aggregated = FALSE;
12738
12739 /* search for the best common variable such that
12740 * val1[var] * consdata0 - val0[var] * consdata1
12741 * has least weighted number of variables
12742 */
12743 bestvarweight = commonidxweight + diffidx0minus1weight;
12744 bestnvars = consdata0->nvars;
12745 bestv = -1;
12746 bestscalarsum = 0.0;
12747 commonvarlindependent = TRUE;
12748 for( v = 0; v < nvarscommon; ++v )
12749 {
12750 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12751 a = consdata1->vals[commonidx1[v]];
12752 b = -consdata0->vals[commonidx0[v]];
12753
12754 /* only try aggregation, if coefficients are integral (numerical stability) */
12756 {
12757 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12758 varweight = diffidx0minus1weight + diffidx1minus0weight;
12759 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12760 scalarsum = REALABS(a) + REALABS(b);
12761 betterscalarsum = (scalarsum < bestscalarsum);
12762 for( i = 0; i < nvarscommon
12763 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12764 {
12765 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12766 if( !SCIPisZero(scip, aggrcoef) )
12767 {
12768 varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12769 nvars++;
12770 }
12771 }
12772 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12773 {
12774 bestv = v;
12775 bestvarweight = varweight;
12776 bestnvars = nvars;
12777 bestscalarsum = scalarsum;
12778 }
12779 }
12780
12781 /* update commonvarlindependent flag, if still TRUE:
12782 * 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
12783 */
12784 if( commonvarlindependent && v > 0 )
12785 commonvarlindependent = SCIPisEQ(scip,
12786 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12787 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12788 }
12789
12790 /* if better aggregation was found, create new constraint and delete old one */
12791 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12792 {
12793 SCIP_CONS* newcons;
12794 SCIP_CONSDATA* newconsdata;
12795 SCIP_VAR** newvars;
12796 SCIP_Real* newvals;
12797 SCIP_Real newlhs;
12798 SCIP_Real newrhs;
12799 int newnvars;
12800
12801 if( bestv != -1 )
12802 {
12803 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12804 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12805 {
12806 a = consdata1->vals[commonidx1[bestv]];
12807 b = -consdata0->vals[commonidx0[bestv]];
12808 }
12809 else
12810 {
12811 a = -consdata1->vals[commonidx1[bestv]];
12812 b = consdata0->vals[commonidx0[bestv]];
12813 }
12814 assert(SCIPisIntegral(scip, a));
12815 assert(SCIPisPositive(scip, a));
12816 assert(SCIPisIntegral(scip, b));
12817 assert(!SCIPisZero(scip, b));
12818 }
12819 else
12820 {
12821 assert(commonvarlindependent);
12822 if( consdata1->vals[commonidx1[0]] > 0.0 )
12823 {
12824 a = consdata1->vals[commonidx1[0]];
12825 b = -consdata0->vals[commonidx0[0]];
12826 }
12827 else
12828 {
12829 a = -consdata1->vals[commonidx1[0]];
12830 b = consdata0->vals[commonidx0[0]];
12831 }
12832 assert(SCIPisPositive(scip, a));
12833 assert(!SCIPisZero(scip, b));
12834
12835 /* if a/b is integral, then we can easily choose integer multipliers */
12836 if( SCIPisIntegral(scip, a/b) )
12837 {
12838 if( a/b > 0 )
12839 {
12840 a /= b;
12841 b = 1.0;
12842 }
12843 else
12844 {
12845 a /= -b;
12846 b = -1.0;
12847 }
12848 }
12849
12850 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12851 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12852 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12853 }
12854
12855 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12856 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12857 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12858 SCIPdebugPrintCons(scip, cons0, NULL);
12859 SCIPdebugPrintCons(scip, cons1, NULL);
12860
12861 /* get temporary memory for creating the new linear constraint */
12862 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12863 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12864
12865 /* calculate the common coefficients, if we have not recognized linear dependency */
12866 newnvars = 0;
12867 if( !commonvarlindependent )
12868 {
12869 for( i = 0; i < nvarscommon; ++i )
12870 {
12871 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12872 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12873
12874 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12875 if( !SCIPisZero(scip, aggrcoef) )
12876 {
12877 assert(newnvars < bestnvars);
12878 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12879 newvals[newnvars] = aggrcoef;
12880 newnvars++;
12881 }
12882 }
12883 }
12884 else
12885 {
12886 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12887#ifndef NDEBUG
12888 for( i = 0; i < nvarscommon; ++i )
12889 {
12890 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12891 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12892
12893 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12894 assert(SCIPisZero(scip, aggrcoef));
12895 }
12896#endif
12897 }
12898
12899 /* calculate the coefficients appearing in cons0 but not in cons1 */
12900 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12901 {
12902 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12903
12904 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12905 assert(!SCIPisZero(scip, aggrcoef));
12906 assert(newnvars < bestnvars);
12907 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12908 newvals[newnvars] = aggrcoef;
12909 newnvars++;
12910 }
12911
12912 /* calculate the coefficients appearing in cons1 but not in cons0 */
12913 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12914 {
12915 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12916
12917 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12918 assert(!SCIPisZero(scip, aggrcoef));
12919 assert(newnvars < bestnvars);
12920 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12921 newvals[newnvars] = aggrcoef;
12922 newnvars++;
12923 }
12924 assert(newnvars == bestnvars);
12925
12926 /* calculate the new left and right hand side of the (in)equality */
12927 assert(!SCIPisInfinity(scip, -consdata1->lhs));
12928 assert(!SCIPisInfinity(scip, consdata1->rhs));
12929 if( SCIPisInfinity(scip, -consdata0->lhs) )
12930 newlhs = -SCIPinfinity(scip);
12931 else
12932 newlhs = a * consdata0->lhs + b * consdata1->lhs;
12933 if( SCIPisInfinity(scip, consdata0->rhs) )
12934 newrhs = SCIPinfinity(scip);
12935 else
12936 newrhs = a * consdata0->rhs + b * consdata1->rhs;
12937
12938 /* create the new linear constraint */
12939 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12944
12945 newconsdata = SCIPconsGetData(newcons);
12946 assert(newconsdata != NULL);
12947
12948 /* copy the upgraded flag from the old cons0 to the new constraint */
12949 newconsdata->upgraded = consdata0->upgraded;
12950
12951 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12952
12953 if( *infeasible )
12954 goto TERMINATE;
12955
12956 /* check, if we really want to use the new constraint instead of the old one:
12957 * use the new one, if the maximum norm doesn't grow too much
12958 */
12959 if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12960 {
12961 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12962 SCIPdebugPrintCons(scip, newcons, NULL);
12963
12964 /* update the statistics: we changed all coefficients */
12965 if( !consdata0->upgraded )
12966 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12967 *aggregated = TRUE;
12968
12969 /* delete the old constraint, and add the new linear constraint to the problem */
12970 SCIP_CALL( SCIPdelCons(scip, cons0) );
12971 SCIP_CALL( SCIPaddCons(scip, newcons) );
12972 }
12973
12974 TERMINATE:
12975 /* release the new constraint */
12976 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12977
12978 /* free temporary memory */
12979 SCIPfreeBufferArray(scip, &newvals);
12980 SCIPfreeBufferArray(scip, &newvars);
12981 }
12982
12983 return SCIP_OKAY;
12984}
12985
12986/** gets the key of the given element */
12987static
12988SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12989{ /*lint --e{715}*/
12990 /* the key is the element itself */
12991 return elem;
12992}
12993
12994/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
12995 * coefficients are either equal or negated
12996 */
12997static
12998SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
12999{
13000 SCIP* scip;
13001 SCIP_CONSDATA* consdata1;
13002 SCIP_CONSDATA* consdata2;
13003 SCIP_Real minscale;
13004 SCIP_Real maxscale;
13005 int i;
13006
13007 assert(key1 != NULL);
13008 assert(key2 != NULL);
13009 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13010 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13011 assert(consdata1->indexsorted);
13012 assert(consdata2->indexsorted);
13013
13014 scip = (SCIP*)userptr;
13015 assert(scip != NULL);
13016
13017 /* if it is the same constraint we dont need to check anything */
13018 if( key1 == key2 )
13019 return TRUE;
13020
13021 /* checks trivial case */
13022 if( consdata1->nvars != consdata2->nvars )
13023 return FALSE;
13024
13025 /* tests if variables are equal */
13026 for( i = 0; i < consdata1->nvars; ++i )
13027 {
13028 if( consdata1->vars[i] != consdata2->vars[i] )
13029 {
13030 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13031 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13032 return FALSE;
13033 }
13034 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13035 }
13036
13037 /* order by maxabsval */
13038 if( consdataGetMaxAbsval(consdata1) > consdataGetMaxAbsval(consdata2) )
13039 SCIPswapPointers((void**)&consdata1, (void**)&consdata2);
13040
13041 /* initialize extremal scales */
13042 minscale = SCIPinfinity(scip);
13043 maxscale = -SCIPinfinity(scip);
13044
13045 /* test if coefficient scales are equal */
13046 for( i = 0; i < consdata1->nvars; ++i )
13047 {
13048 SCIP_Real scale = consdata2->vals[i] / consdata1->vals[i];
13049
13050 if( minscale > scale )
13051 {
13052 minscale = scale;
13053
13054 if( SCIPisLT(scip, minscale, maxscale) )
13055 return FALSE;
13056 }
13057
13058 if( maxscale < scale )
13059 {
13060 maxscale = scale;
13061
13062 if( SCIPisLT(scip, minscale, maxscale) )
13063 return FALSE;
13064 }
13065 }
13066
13067 return TRUE;
13068}
13069
13070/** returns the hash value of the key */
13071static
13072SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13073{
13074 SCIP_CONSDATA* consdata;
13075 int minidx;
13076 int mididx;
13077 int maxidx;
13078#ifndef NDEBUG
13079 SCIP* scip;
13080
13081 scip = (SCIP*)userptr;
13082 assert(scip != NULL);
13083#endif
13084
13085 assert(key != NULL);
13086 consdata = SCIPconsGetData((SCIP_CONS*)key);
13087 assert(consdata != NULL);
13088 assert(consdata->nvars > 0);
13089
13090 assert(consdata->indexsorted);
13091
13092 minidx = SCIPvarGetIndex(consdata->vars[0]);
13093 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13094 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13095
13096 /* using only the variable indices as hash, since the values are compared by epsilon */
13097 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
13098}
13099
13100/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13101 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13102 */
13103static
13105 SCIP_CONS* cons /**< linear constraint */
13106 )
13107{
13108 SCIP_CONSDATA* consdata;
13109
13110 assert(cons != NULL);
13111
13112 consdata = SCIPconsGetData(cons);
13113 assert(consdata != NULL);
13114
13115 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13116}
13117
13118/** updates the hashtable such that out of all constraints in the hashtable that are detected
13119 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13120 * and all others are removed from the hashtable and stored in the given array
13121 */
13122static
13124 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13125 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13126 * upon return will contain the constraint that should be kept */
13127 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13128 * these constraints where removed from the hashtable */
13129 int* nparallelconss /**< pointer to return number of parallel constraints */
13130 )
13131{
13132 SCIP_CONS* parallelcons;
13133 unsigned int querykey;
13134
13135 *nparallelconss = 0;
13136 querykey = getParallelConsKey(*querycons);
13137
13138 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13139 {
13140 unsigned int conskey = getParallelConsKey(parallelcons);
13141
13142 if( conskey < querykey )
13143 {
13144 parallelconss[(*nparallelconss)++] = *querycons;
13145 *querycons = parallelcons;
13146 querykey = conskey;
13147 }
13148 else
13149 {
13150 parallelconss[(*nparallelconss)++] = parallelcons;
13151 }
13152
13153 /* if the constraint that just came out of the hash table is the one that is kept,
13154 * we do not need to look into the hashtable again, since the invariant is that
13155 * in the hashtable only pair-wise non-parallel constraints are contained.
13156 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13157 * could be contained due to non-transitivity of the equality comparison.
13158 * Also we can return immediately, since parallelcons is already contained in the
13159 * hashtable and we do not need to remove and reinsert it.
13160 */
13161 if( *querycons == parallelcons )
13162 return SCIP_OKAY;
13163
13164 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13165 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13166 }
13167
13168 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13169 * comnpares equal to querycons at this point
13170 */
13171#ifndef NDEBUG
13172 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13173#else
13174 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13175#endif
13176
13177 return SCIP_OKAY;
13178}
13179
13180/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13181 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13182 */
13183static
13185 SCIP* scip, /**< SCIP data structure */
13186 BMS_BLKMEM* blkmem, /**< block memory */
13187 SCIP_CONS** conss, /**< constraint set */
13188 int nconss, /**< number of constraints in constraint set */
13189 int* firstchange, /**< pointer to store first changed constraint */
13190 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13191 int* ndelconss, /**< pointer to count number of deleted constraints */
13192 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13193 )
13194{
13195 SCIP_HASHTABLE* hashtable;
13196 SCIP_CONS** parallelconss;
13197 int nparallelconss;
13198 int hashtablesize;
13199 int c;
13200
13201 assert(scip != NULL);
13202 assert(blkmem != NULL);
13203 assert(conss != NULL);
13204 assert(firstchange != NULL);
13205 assert(cutoff != NULL);
13206 assert(ndelconss != NULL);
13207 assert(nchgsides != NULL);
13208
13209 /* create a hash table for the constraint set */
13210 hashtablesize = nconss;
13211 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13212 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13213
13214 SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13215
13216 /* check all constraints in the given set for redundancy */
13217 for( c = 0; c < nconss; ++c )
13218 {
13219 SCIP_CONS* cons0;
13220 SCIP_CONSDATA* consdata0;
13221
13222 cons0 = conss[c];
13223
13224 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13225 continue;
13226
13227 /* do not check for parallel constraints if they should not be upgraded */
13228 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13229 continue;
13230
13231 /* check for interuption */
13232 if( c % 1000 == 0 && SCIPisStopped(scip) )
13233 break;
13234
13235 /* sorts the constraint */
13236 consdata0 = SCIPconsGetData(cons0);
13237 assert(consdata0 != NULL);
13238 SCIP_CALL( consdataSort(scip, consdata0) );
13239 assert(consdata0->indexsorted);
13240
13241 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13242 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13243 * first variable is positive
13244 * Also inserts cons0 into the hashtable.
13245 */
13246 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13247
13248 if( nparallelconss != 0 )
13249 {
13250 SCIP_Real lhs;
13251 SCIP_Real rhs;
13252
13253 int i;
13254
13255 /* cons0 may have been changed in retrieveParallelConstraints() */
13256 consdata0 = SCIPconsGetData(cons0);
13257
13258 lhs = consdata0->lhs;
13259 rhs = consdata0->rhs;
13260
13261 for( i = 0; i < nparallelconss; ++i )
13262 {
13263 SCIP_CONS* consdel;
13264 SCIP_CONSDATA* consdatadel;
13265 SCIP_Real scale;
13266
13267 consdel = parallelconss[i];
13268 consdatadel = SCIPconsGetData(consdel);
13269
13270 /* do not delete constraint if it should not be upgraded */
13271 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13272 continue;
13273
13274 assert(SCIPconsIsActive(consdel));
13275 assert(!SCIPconsIsModifiable(consdel));
13276
13277 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13278 * delete old constraints afterwards
13279 */
13280 assert(consdatadel != NULL);
13281 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13282
13283 assert(consdatadel->indexsorted);
13284 assert(consdata0->vars[0] == consdatadel->vars[0]);
13285
13286 scale = consdata0->vals[0] / consdatadel->vals[0];
13287 assert(scale != 0.0);
13288
13289 /* in debug mode, check that all coefficients are equal with respect to epsilon
13290 * if the constraints are in equilibrium scale
13291 */
13292#ifndef NDEBUG
13293 {
13294 assert(consdata0->validmaxabsval);
13295 assert(consdatadel->validmaxabsval);
13296 int k;
13297 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13298 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13299
13300 for( k = 0; k < consdata0->nvars; ++k )
13301 {
13302 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13303 }
13304 }
13305#endif
13306
13307 if( scale > 0.0 )
13308 {
13309 /* the coefficients of both constraints are parallel with a positive scale */
13310 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13311 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13312 SCIPdebugPrintCons(scip, cons0, NULL);
13313 SCIPdebugPrintCons(scip, consdel, NULL);
13314
13315 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13316 lhs = MAX(scale * consdatadel->lhs, lhs);
13317
13318 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13319 rhs = MIN(scale * consdatadel->rhs, rhs);
13320 }
13321 else
13322 {
13323 /* the coefficients of both rows are negations */
13324 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13325 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13326 SCIPdebugPrintCons(scip, cons0, NULL);
13327 SCIPdebugPrintCons(scip, consdel, NULL);
13328
13329 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13330 lhs = MAX(scale * consdatadel->rhs, lhs);
13331
13332 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13333 rhs = MIN(scale * consdatadel->lhs, rhs);
13334 }
13335
13336 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13337 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13338
13339 /* delete consdel */
13340 assert( ! consdata0->upgraded || consdatadel->upgraded );
13341 SCIP_CALL( SCIPdelCons(scip, consdel) );
13342 if( !consdatadel->upgraded )
13343 (*ndelconss)++;
13344 }
13345
13346 if( SCIPisFeasLT(scip, rhs, lhs) )
13347 {
13348 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13349 *cutoff = TRUE;
13350 break;
13351 }
13352
13353 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13354 if( lhs > rhs )
13355 {
13356 rhs = (lhs + rhs)/2;
13357 lhs = rhs;
13358 }
13359
13360 /* update lhs and rhs of cons0 */
13361 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13362 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13363
13364 /* update the first changed constraint to begin the next aggregation round with */
13365 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13366 *firstchange = SCIPconsGetPos(cons0);
13367
13368 assert(SCIPconsIsActive(cons0));
13369 }
13370 }
13371#ifdef SCIP_MORE_DEBUG
13372 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13374#endif
13375
13376 SCIPfreeBufferArray(scip, &parallelconss);
13377
13378 /* free hash table */
13379 SCIPhashtableFree(&hashtable);
13380
13381 return SCIP_OKAY;
13382}
13383
13384/** compares constraint with all prior constraints for possible redundancy or aggregation,
13385 * and removes or changes constraint accordingly
13386 */
13387static
13389 SCIP* scip, /**< SCIP data structure */
13390 SCIP_CONS** conss, /**< constraint set */
13391 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13392 int chkind, /**< index of constraint to check against all prior indices upto startind */
13393 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13394 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13395 int* ndelconss, /**< pointer to count number of deleted constraints */
13396 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13397 int* nchgcoefs /**< pointer to count number of changed coefficients */
13398 )
13399{
13400 SCIP_CONS* cons0;
13401 SCIP_CONSDATA* consdata0;
13402 int* commonidx0;
13403 int* commonidx1;
13404 int* diffidx0minus1;
13405 int* diffidx1minus0;
13406 uint64_t possignature0;
13407 uint64_t negsignature0;
13408 SCIP_Bool cons0changed;
13409 SCIP_Bool cons0isequality;
13410 int diffidx1minus0size;
13411 int c;
13412 SCIP_Real cons0lhs;
13413 SCIP_Real cons0rhs;
13414 SCIP_Bool cons0upgraded;
13415
13416 assert(scip != NULL);
13417 assert(conss != NULL);
13418 assert(firstchange <= chkind);
13419 assert(cutoff != NULL);
13420 assert(ndelconss != NULL);
13421 assert(nchgsides != NULL);
13422 assert(nchgcoefs != NULL);
13423
13424 /* get the constraint to be checked against all prior constraints */
13425 cons0 = conss[chkind];
13426 assert(cons0 != NULL);
13427 assert(SCIPconsIsActive(cons0));
13428 assert(!SCIPconsIsModifiable(cons0));
13429
13430 consdata0 = SCIPconsGetData(cons0);
13431 assert(consdata0 != NULL);
13432 assert(consdata0->nvars >= 1);
13433 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13434
13435 /* sort the constraint */
13436 SCIP_CALL( consdataSort(scip, consdata0) );
13437
13438 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13439 consdataCalcSignatures(consdata0);
13440 possignature0 = consdata0->possignature;
13441 negsignature0 = consdata0->negsignature;
13442
13443 /* get temporary memory for indices of common variables */
13444 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13445 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13446 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13447 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13448 diffidx1minus0size = consdata0->nvars;
13449
13450 cons0lhs = consdata0->lhs;
13451 cons0rhs = consdata0->rhs;
13452 cons0upgraded = consdata0->upgraded;
13453
13454 /* check constraint against all prior constraints */
13455 cons0changed = consdata0->changed;
13456 consdata0->changed = FALSE;
13457 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13458 {
13459 SCIP_CONS* cons1;
13460 SCIP_CONSDATA* consdata1;
13461 uint64_t possignature1;
13462 uint64_t negsignature1;
13463 SCIP_Bool cons0dominateslhs;
13464 SCIP_Bool cons1dominateslhs;
13465 SCIP_Bool cons0dominatesrhs;
13466 SCIP_Bool cons1dominatesrhs;
13467 SCIP_Bool cons1isequality;
13468 SCIP_Bool coefsequal;
13469 SCIP_Bool coefsnegated;
13470 SCIP_Bool tryaggregation;
13471 int nvarscommon;
13472 int nvars0minus1;
13473 int nvars1minus0;
13474 int commonidxweight;
13475 int diffidx0minus1weight;
13476 int diffidx1minus0weight;
13477 int v0;
13478 int v1;
13479
13480 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13481 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13482 assert(cons0upgraded == consdata0->upgraded);
13483
13484 cons1 = conss[c];
13485
13486 /* cons1 has become inactive during presolving of constraint pairs */
13487 if( cons1 == NULL )
13488 continue;
13489
13490 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13491 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13492
13493 consdata1 = SCIPconsGetData(cons1);
13494 assert(consdata1 != NULL);
13495
13496 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13497 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13498 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13499
13500 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13501 if( !cons0changed && !consdata1->changed )
13502 continue;
13503
13504 /* if both constraints are already upgraded, skip the pair;
13505 * because changes on these constraints cannot be applied to the instance anymore */
13506 if( cons0upgraded && consdata1->upgraded )
13507 continue;
13508
13509 assert(consdata1->nvars >= 1);
13510
13511 /* sort the constraint */
13512 SCIP_CALL( consdataSort(scip, consdata1) );
13513
13514 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13515 consdataCalcSignatures(consdata1);
13516 possignature1 = consdata1->possignature;
13517 negsignature1 = consdata1->negsignature;
13518
13519 /* the signatures give a quick test to check for domination and equality of coefficients */
13520 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13521 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13522 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13523 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13524 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13525 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13526 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13527 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13528 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13529 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13530 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13531 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13532 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13533 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13534 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13535 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13536 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13537 && !coefsequal && !coefsnegated && !tryaggregation )
13538 continue;
13539
13540 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13541 if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13542 {
13543 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13544 diffidx1minus0size = consdata1->nvars;
13545 }
13546
13547 /* check consdata0 against consdata1:
13548 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13549 * consdata0 dominates consdata1 w.r.t. left hand side
13550 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13551 * consdata0 dominates consdata1 w.r.t. right hand side
13552 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13553 * ranged row (or equality)
13554 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13555 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13556 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13557 * number of continuous and integer variables are preferred:
13558 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13559 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13560 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13561 * to be positive to not switch the sense of the (in)equality cons0
13562 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13563 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13564 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13565 * to be positive to not switch the sense of the (in)equality cons1
13566 */
13567
13568 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13569 nvarscommon = 0;
13570 commonidxweight = 0;
13571 nvars0minus1 = 0;
13572 diffidx0minus1weight = 0;
13573 nvars1minus0 = 0;
13574 diffidx1minus0weight = 0;
13575 v0 = 0;
13576 v1 = 0;
13577 while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13578 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13579 || coefsequal || coefsnegated || tryaggregation) )
13580 {
13581 SCIP_VAR* var;
13582 SCIP_Real val0;
13583 SCIP_Real val1;
13584 int varcmp;
13585
13586 /* test, if variable appears in only one or in both constraints */
13587 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13588 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13589 else if( v0 < consdata0->nvars )
13590 varcmp = -1;
13591 else
13592 varcmp = +1;
13593
13594 switch( varcmp )
13595 {
13596 case -1:
13597 /* variable doesn't appear in consdata1 */
13598 var = consdata0->vars[v0];
13599 val0 = consdata0->vals[v0];
13600 val1 = 0.0;
13601 if( tryaggregation )
13602 {
13603 diffidx0minus1[nvars0minus1] = v0;
13604 nvars0minus1++;
13605 diffidx0minus1weight += getVarWeight(var);
13606 }
13607 v0++;
13608 coefsequal = FALSE;
13609 coefsnegated = FALSE;
13610 break;
13611
13612 case +1:
13613 /* variable doesn't appear in consdata0 */
13614 var = consdata1->vars[v1];
13615 val0 = 0.0;
13616 val1 = consdata1->vals[v1];
13617 if( tryaggregation )
13618 {
13619 diffidx1minus0[nvars1minus0] = v1;
13620 nvars1minus0++;
13621 diffidx1minus0weight += getVarWeight(var);
13622 }
13623 v1++;
13624 coefsequal = FALSE;
13625 coefsnegated = FALSE;
13626 break;
13627
13628 case 0:
13629 /* variable appears in both constraints */
13630 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13631 var = consdata0->vars[v0];
13632 val0 = consdata0->vals[v0];
13633 val1 = consdata1->vals[v1];
13634 if( tryaggregation )
13635 {
13636 commonidx0[nvarscommon] = v0;
13637 commonidx1[nvarscommon] = v1;
13638 nvarscommon++;
13639 commonidxweight += getVarWeight(var);
13640 }
13641 v0++;
13642 v1++;
13643 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13644 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13645 break;
13646
13647 default:
13648 SCIPerrorMessage("invalid comparison result\n");
13649 SCIPABORT();
13650 var = NULL;
13651 val0 = 0.0;
13652 val1 = 0.0;
13653 }
13654 assert(var != NULL);
13655
13656 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13657 if( SCIPisGT(scip, val0, val1) )
13658 {
13660 {
13661 cons0dominatesrhs = FALSE;
13662 cons1dominateslhs = FALSE;
13663 }
13665 {
13666 cons0dominateslhs = FALSE;
13667 cons1dominatesrhs = FALSE;
13668 }
13669 }
13670 else if( SCIPisLT(scip, val0, val1) )
13671 {
13673 {
13674 cons0dominateslhs = FALSE;
13675 cons1dominatesrhs = FALSE;
13676 }
13678 {
13679 cons0dominatesrhs = FALSE;
13680 cons1dominateslhs = FALSE;
13681 }
13682 }
13683 }
13684
13685 /* check for disaggregated ranged rows */
13686 if( coefsequal || coefsnegated )
13687 {
13688 SCIP_CONS* consstay;
13689 SCIP_CONS* consdel;
13690#ifndef NDEBUG
13691 SCIP_CONSDATA* consdatastay;
13692#endif
13693 SCIP_CONSDATA* consdatadel;
13694 SCIP_Real lhs;
13695 SCIP_Real rhs;
13696 int consinddel;
13697
13698 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13699 * best left and right hand sides; delete the old constraints afterwards
13700 */
13701 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13702 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13703 SCIPdebugPrintCons(scip, cons0, NULL);
13704 SCIPdebugPrintCons(scip, cons1, NULL);
13705
13706 if( coefsequal )
13707 {
13708 /* the coefficients of both rows are equal */
13709 lhs = MAX(consdata0->lhs, consdata1->lhs);
13710 rhs = MIN(consdata0->rhs, consdata1->rhs);
13711 }
13712 else
13713 {
13714 /* the coefficients of both rows are negations */
13715 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13716 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13717 }
13718 if( SCIPisFeasLT(scip, rhs, lhs) )
13719 {
13720 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13721 *cutoff = TRUE;
13722 break;
13723 }
13724
13725 /* check which constraint has to stay;
13726 * changes applied to an upgraded constraint will not be considered in the instance */
13727 if( consdata0->upgraded )
13728 {
13729 assert(!consdata1->upgraded);
13730 consstay = cons1;
13731#ifndef NDEBUG
13732 consdatastay = consdata1;
13733#endif
13734
13735 consdel = cons0;
13736 consdatadel = consdata0;
13737 consinddel = chkind;
13738 }
13739 else
13740 {
13741 consstay = cons0;
13742#ifndef NDEBUG
13743 consdatastay = consdata0;
13744#endif
13745
13746 consdel = cons1;
13747 consdatadel = consdata1;
13748 consinddel = c;
13749 }
13750
13751 /* update the sides of consstay */
13752 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13753 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13754 if( !consdata0->upgraded )
13755 {
13756 assert(consstay == cons0);
13757 cons0lhs = consdata0->lhs;
13758 cons0rhs = consdata0->rhs;
13759 }
13760
13761 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13762 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13763
13764 assert( !consdatastay->upgraded );
13765 /* delete consdel */
13766 SCIP_CALL( SCIPdelCons(scip, consdel) );
13767 conss[consinddel] = NULL;
13768 if( !consdatadel->upgraded )
13769 (*ndelconss)++;
13770 continue;
13771 }
13772
13773 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13774 * redundant
13775 */
13776 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13777 {
13778 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13779 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13780 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13781 SCIPdebugPrintCons(scip, cons0, NULL);
13782 SCIPdebugPrintCons(scip, cons1, NULL);
13783
13784 /* check for infeasibility */
13785 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13786 {
13787 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13788 *cutoff = TRUE;
13789 break;
13790 }
13791
13792 /* remove redundant left hand side */
13793 if( !SCIPisInfinity(scip, -consdata0->lhs) )
13794 {
13795 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13796 cons0lhs = consdata0->lhs;
13797 cons0isequality = FALSE;
13798 if( !consdata0->upgraded )
13799 {
13800 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13801 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13802
13803 (*nchgsides)++;
13804 }
13805 }
13806 }
13807 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13808 {
13809 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13810 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13811 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13812 SCIPdebugPrintCons(scip, cons1, NULL);
13813 SCIPdebugPrintCons(scip, cons0, NULL);
13814
13815 /* check for infeasibility */
13816 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13817 {
13818 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13819 *cutoff = TRUE;
13820 break;
13821 }
13822
13823 /* remove redundant left hand side */
13824 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13825 {
13826 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13827 cons1isequality = FALSE;
13828 if( !consdata1->upgraded )
13829 {
13830 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13831 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13832
13833 (*nchgsides)++;
13834 }
13835 }
13836 }
13837 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13838 {
13839 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13840 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13841 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13842 SCIPdebugPrintCons(scip, cons0, NULL);
13843 SCIPdebugPrintCons(scip, cons1, NULL);
13844
13845 /* check for infeasibility */
13846 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13847 {
13848 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13849 *cutoff = TRUE;
13850 break;
13851 }
13852
13853 /* remove redundant right hand side */
13854 if( !SCIPisInfinity(scip, consdata0->rhs) )
13855 {
13856 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13857 cons0rhs = consdata0->rhs;
13858 cons0isequality = FALSE;
13859 if( !consdata0->upgraded )
13860 {
13861 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13862 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13863
13864 (*nchgsides)++;
13865 }
13866 }
13867 }
13868 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13869 {
13870 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13871 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13872 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13873 SCIPdebugPrintCons(scip, cons1, NULL);
13874 SCIPdebugPrintCons(scip, cons0, NULL);
13875
13876 /* check for infeasibility */
13877 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13878 {
13879 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13880 *cutoff = TRUE;
13881 break;
13882 }
13883
13884 /* remove redundant right hand side */
13885 if( !SCIPisInfinity(scip, consdata1->rhs) )
13886 {
13887 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13888 cons1isequality = FALSE;
13889 if( !consdata1->upgraded )
13890 {
13891 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13892 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13893
13894 (*nchgsides)++;
13895 }
13896 }
13897 }
13898
13899 /* check for now redundant constraints */
13900 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13901 {
13902 /* consdata0 became redundant */
13903 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13904 SCIP_CALL( SCIPdelCons(scip, cons0) );
13905 conss[chkind] = NULL;
13906 if( !consdata0->upgraded )
13907 {
13908 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13909 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13910
13911 (*ndelconss)++;
13912 }
13913 continue;
13914 }
13915 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13916 {
13917 /* consdata1 became redundant */
13918 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13919 SCIP_CALL( SCIPdelCons(scip, cons1) );
13920 conss[c] = NULL;
13921 if( !consdata1->upgraded )
13922 {
13923 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13924 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13925
13926 (*ndelconss)++;
13927 }
13928 continue;
13929 }
13930
13931 /* check, if we want to aggregate an (in)equality with an equality:
13932 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13933 */
13934 if( tryaggregation )
13935 {
13936 SCIP_Bool aggregated;
13937
13938 assert(consdata0->nvars == nvarscommon + nvars0minus1);
13939 assert(consdata1->nvars == nvarscommon + nvars1minus0);
13940
13941 aggregated = FALSE;
13942 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13943 {
13944 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13945 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13946 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13947 nchgcoefs, &aggregated, cutoff) );
13948
13949 if( *cutoff )
13950 break;
13951
13952 /* update array of active constraints */
13953 if( aggregated )
13954 {
13955 assert(!SCIPconsIsActive(cons0));
13956 assert(SCIPconsIsActive(cons1));
13957 conss[chkind] = NULL;
13958 }
13959 }
13960 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13961 {
13962 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13963 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13964 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13965 nchgcoefs, &aggregated, cutoff) );
13966
13967 if( *cutoff )
13968 break;
13969
13970 /* update array of active constraints */
13971 if( aggregated )
13972 {
13973 assert(!SCIPconsIsActive(cons1));
13974 assert(SCIPconsIsActive(cons0));
13975 conss[c] = NULL;
13976 }
13977 }
13978 }
13979 }
13980
13981 /* free temporary memory */
13982 SCIPfreeBufferArray(scip, &diffidx1minus0);
13983 SCIPfreeBufferArray(scip, &diffidx0minus1);
13984 SCIPfreeBufferArray(scip, &commonidx1);
13985 SCIPfreeBufferArray(scip, &commonidx0);
13986
13987 return SCIP_OKAY;
13988}
13989
13990/** do stuffing presolving on a single constraint */
13991static
13993 SCIP* scip, /**< SCIP data structure */
13994 SCIP_CONS* cons, /**< linear constraint */
13995 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
13996 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
13997 * constraints using the cheapest variable? */
13998 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13999 int* nfixedvars, /**< pointer to count the total number of fixed variables */
14000 int* nchgbds /**< pointer to count the total number of tightened bounds */
14001 )
14002{
14003 SCIP_CONSDATA* consdata;
14004 SCIP_Real* ratios;
14005 int* varpos;
14006 SCIP_Bool* swapped;
14007 SCIP_VAR** vars;
14008 SCIP_Real* vals;
14009 SCIP_VAR* var;
14010 SCIP_Real lb;
14011 SCIP_Real ub;
14012 SCIP_Real minactivity;
14013 SCIP_Real maxactivity;
14014 SCIP_Real maxcondactivity;
14015 SCIP_Real mincondactivity;
14016 SCIP_Real rhs;
14017 SCIP_Real val;
14018 SCIP_Real obj;
14019 SCIP_Real factor;
14020 SCIP_Bool isminacttight;
14021 SCIP_Bool ismaxacttight;
14022 SCIP_Bool isminsettoinfinity;
14023 SCIP_Bool ismaxsettoinfinity;
14024 SCIP_Bool tryfixing;
14025 int nsingletons;
14026 int idx;
14027 int v;
14028 int nvars;
14029
14030 assert(scip != NULL);
14031 assert(cons != NULL);
14032 assert(nfixedvars != NULL);
14033
14034 consdata = SCIPconsGetData(cons);
14035
14036 /* we only want to run for inequalities */
14037 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14038 return SCIP_OKAY;
14039
14040 if( singlevarstuffing )
14041 {
14042 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
14043 &isminsettoinfinity, &ismaxsettoinfinity);
14044 }
14045 else
14046 {
14047 minactivity = SCIP_INVALID;
14048 maxactivity = SCIP_INVALID;
14049 isminsettoinfinity = FALSE;
14050 ismaxsettoinfinity = FALSE;
14051 }
14052
14053 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14054 * the new maxactivity is minus the old minactivity then
14055 */
14056 if( SCIPisInfinity(scip, consdata->rhs) )
14057 {
14058 rhs = -consdata->lhs;
14059 factor = -1.0;
14060 maxactivity = -minactivity;
14061 ismaxsettoinfinity = isminsettoinfinity;
14062 }
14063 else
14064 {
14065 assert(SCIPisInfinity(scip, -consdata->lhs));
14066 rhs = consdata->rhs;
14067 factor = 1.0;
14068 }
14069
14070 nvars = consdata->nvars;
14071 vars = consdata->vars;
14072 vals = consdata->vals;
14073
14074 /* check for continuous singletons */
14075 if( singletonstuffing )
14076 {
14077 for( v = 0; v < nvars; ++v )
14078 {
14079 var = vars[v];
14080
14083 break;
14084 }
14085 }
14086 else
14087 /* we don't want to go into the next block */
14088 v = nvars;
14089
14090 /* a singleton was found -> perform singleton variable stuffing */
14091 if( v < nvars )
14092 {
14093 assert(singletonstuffing);
14094
14095 SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14096 SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14097 SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14098
14099 tryfixing = TRUE;
14100 nsingletons = 0;
14101 mincondactivity = 0.0;
14102 maxcondactivity = 0.0;
14103
14104 for( v = 0; v < nvars; ++v )
14105 {
14106 var = vars[v];
14107 lb = SCIPvarGetLbGlobal(var);
14108 ub = SCIPvarGetUbGlobal(var);
14109 obj = SCIPvarGetObj(var);
14110 val = factor * vals[v];
14111
14112 assert(!SCIPisZero(scip, val));
14113
14114 /* the variable is a singleton and continuous */
14117 {
14118 if( SCIPisNegative(scip, obj) && val > 0 )
14119 {
14120 /* case 1: obj < 0 and coef > 0 */
14121 if( SCIPisInfinity(scip, -lb) )
14122 {
14123 tryfixing = FALSE;
14124 break;
14125 }
14126
14127 maxcondactivity += val * lb;
14128 mincondactivity += val * lb;
14129 swapped[v] = FALSE;
14130 ratios[nsingletons] = obj / val;
14131 varpos[nsingletons] = v;
14132 nsingletons++;
14133 }
14134 else if( SCIPisPositive(scip, obj) && val < 0 )
14135 {
14136 /* case 2: obj > 0 and coef < 0 */
14137 if( SCIPisInfinity(scip, ub) )
14138 {
14139 tryfixing = FALSE;
14140 break;
14141 }
14142 /* multiply column by (-1) to become case 1.
14143 * now bounds are swapped: ub := -lb, lb := -ub
14144 */
14145
14146 maxcondactivity += val * ub;
14147 mincondactivity += val * ub;
14148 swapped[v] = TRUE;
14149 ratios[nsingletons] = obj / val;
14150 varpos[nsingletons] = v;
14151 nsingletons++;
14152 }
14153 else if( val > 0 )
14154 {
14155 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14156 * we only consider the lower bound for the constants
14157 */
14158 assert(!SCIPisNegative(scip, obj));
14159
14160 if( SCIPisInfinity(scip, -lb) )
14161 {
14162 /* maybe unbounded */
14163 tryfixing = FALSE;
14164 break;
14165 }
14166
14167 maxcondactivity += val * lb;
14168 mincondactivity += val * lb;
14169 }
14170 else
14171 {
14172 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14173 * we only consider the upper bound for the constants
14174 */
14175 assert(!SCIPisPositive(scip, obj));
14176 assert(val < 0);
14177
14178 if( SCIPisInfinity(scip, ub) )
14179 {
14180 /* maybe unbounded */
14181 tryfixing = FALSE;
14182 break;
14183 }
14184
14185 maxcondactivity += val * ub;
14186 mincondactivity += val * ub;
14187 }
14188 }
14189 else
14190 {
14191 /* consider contribution of discrete variables, non-singleton
14192 * continuous variables and variables with more than one lock
14193 */
14194 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14195 {
14196 tryfixing = FALSE;
14197 break;
14198 }
14199
14200 if( val > 0 )
14201 {
14202 maxcondactivity += val * ub;
14203 mincondactivity += val * lb;
14204 }
14205 else
14206 {
14207 maxcondactivity += val * lb;
14208 mincondactivity += val * ub;
14209 }
14210 }
14211 }
14212 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14213 {
14214 SCIP_Real delta;
14215 SCIP_Bool tightened;
14216#ifdef SCIP_DEBUG
14217 int oldnfixedvars = *nfixedvars;
14218 int oldnchgbds = *nchgbds;
14219#endif
14220
14221 SCIPsortRealInt(ratios, varpos, nsingletons);
14222
14223 /* verify which singleton continuous variables can be fixed */
14224 for( v = 0; v < nsingletons; ++v )
14225 {
14226 idx = varpos[v];
14227 var = vars[idx];
14228 val = factor * vals[idx];
14229 lb = SCIPvarGetLbGlobal(var);
14230 ub = SCIPvarGetUbGlobal(var);
14231
14232 assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14233 assert((val < 0) == swapped[idx]);
14234 val = REALABS(val);
14235
14236 /* stop fixing if variable bounds are not finite */
14237 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14238 break;
14239
14243
14244 /* calculate the change in the row activities if this variable changes
14245 * its value from its worst to its best bound
14246 */
14247 if( swapped[idx] )
14248 delta = -(lb - ub) * val;
14249 else
14250 delta = (ub - lb) * val;
14251
14252 assert(!SCIPisNegative(scip, delta));
14253
14254 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14255 {
14256 if( swapped[idx] )
14257 {
14258 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14259 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14260 }
14261 else
14262 {
14263 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14264 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14265 }
14266
14267 if( *cutoff )
14268 break;
14269 if( tightened )
14270 {
14271 (*nfixedvars)++;
14272 }
14273 }
14274 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14275 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14276 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14277 * troubles in case of large bounds.
14278 */
14279 else if( SCIPisLE(scip, rhs, mincondactivity) )
14280 {
14281 if( swapped[idx] )
14282 {
14283 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14284 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14285 }
14286 else
14287 {
14288 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14289 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14290 }
14291
14292 if( *cutoff )
14293 break;
14294 if( tightened )
14295 {
14296 (*nfixedvars)++;
14297 }
14298 }
14299
14300 maxcondactivity += delta;
14301 mincondactivity += delta;
14302 }
14303
14304#ifdef SCIP_DEBUG
14305 if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14306 {
14307 SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14308 }
14309#endif
14310 }
14311
14312 SCIPfreeBufferArray(scip, &swapped);
14313 SCIPfreeBufferArray(scip, &ratios);
14314 SCIPfreeBufferArray(scip, &varpos);
14315 }
14316
14317 /* perform single-variable stuffing:
14318 * for a linear inequality
14319 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14320 * with a_i > 0 and objective coefficients c_i < 0,
14321 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14322 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14323 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14324 * is redundant.
14325 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14326 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14327 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14328 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14329 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14330 * upper bound.
14331 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14332 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14333 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14334 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14335 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14336 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14337 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14338 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14339 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14340 * c_k * ceil((maxactivity - rhs)/val) is still better than
14341 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14342 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14343 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14344 * sign of coefficients in constraint and objective prevent the use of this method.
14345 */
14346 if( singlevarstuffing && !ismaxsettoinfinity )
14347 {
14348 SCIP_Real bestratio = -SCIPinfinity(scip);
14349 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14350 SCIP_Real ratio;
14351 int bestindex = -1;
14352 int bestuplocks = 0;
14353 int bestdownlocks = 1;
14354 int downlocks;
14355 int uplocks;
14356 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14357 SCIPdebug( int oldnchgbds = *nchgbds; )
14358
14359 /* loop over all variables to identify the best and second-best ratio */
14360 for( v = 0; v < nvars; ++v )
14361 {
14362 var = vars[v];
14363 obj = SCIPvarGetObj(var);
14364 val = factor * vals[v];
14365
14366 assert(!SCIPisZero(scip, val));
14367
14368 ratio = obj / val;
14369
14370 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14371 if( !SCIPisNegative(scip, ratio) )
14372 {
14373 bestindex = -1;
14374 break;
14375 }
14376
14377 if( val > 0 )
14378 {
14381 }
14382 else
14383 {
14386 }
14387
14388 /* better ratio, update best candidate
14389 * @todo use some tolerance
14390 * @todo check size of domain and updated ratio for integer variables already?
14391 */
14392 if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14393 || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14395 {
14396 /* best index becomes second-best*/
14397 if( bestindex != -1 )
14398 {
14399 /* second-best index must not have more than 1 uplock */
14400 if( bestuplocks > 1 )
14401 {
14402 bestindex = -1;
14403 break;
14404 }
14405 else
14406 {
14407 secondbestratio = bestratio;
14408 }
14409 }
14410 bestdownlocks = downlocks;
14411 bestuplocks = uplocks;
14412 bestratio = ratio;
14413 bestindex = v;
14414
14415 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14416 * if it is not the best, it has too many uplocks -> not applicable
14417 */
14418 if( bestdownlocks > 0 && bestuplocks > 1 )
14419 {
14420 bestindex = -1;
14421 break;
14422 }
14423 }
14424 else
14425 {
14426 /* non-best index must not have more than 1 uplock */
14427 if( uplocks > 1 )
14428 {
14429 bestindex = -1;
14430 break;
14431 }
14432 /* update second-best ratio */
14433 if( ratio > secondbestratio )
14434 {
14435 secondbestratio = ratio;
14436 }
14437 }
14438 }
14439
14440 /* check if we can apply single variable stuffing */
14441 if( bestindex != -1 && bestdownlocks == 0 )
14442 {
14443 SCIP_Bool tightened = FALSE;
14444 SCIP_Real bounddelta;
14445
14446 var = vars[bestindex];
14447 obj = SCIPvarGetObj(var);
14448 val = factor * vals[bestindex];
14449 lb = SCIPvarGetLbGlobal(var);
14450 ub = SCIPvarGetUbGlobal(var);
14451 tryfixing = TRUE;
14452
14453 if( val < 0 )
14454 {
14455 assert(!SCIPisNegative(scip, obj));
14456
14457 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14458 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14459 {
14460 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14461 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14462 assert(SCIPisPositive(scip, activitydelta));
14463
14464 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14465
14466 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14467 assert(SCIPisPositive(scip, bounddelta));
14468 }
14469 else
14470 bounddelta = (maxactivity - rhs)/-val;
14471
14472 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14473
14474 if( tryfixing )
14475 {
14477
14478 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14479 {
14480 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14481 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14482 }
14483 else
14484 {
14485 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14486 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14487 }
14488 }
14489 }
14490 else
14491 {
14492 assert(!SCIPisPositive(scip, obj));
14493
14494 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14495 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14496 {
14497 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14498 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14499 assert(SCIPisPositive(scip, activitydelta));
14500
14501 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14502
14503 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14504 assert(SCIPisPositive(scip, bounddelta));
14505 }
14506 else
14507 bounddelta = (maxactivity - rhs)/val;
14508
14509 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14510
14511 if( tryfixing )
14512 {
14514
14515 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14516 {
14517 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14518 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14519 }
14520 else
14521 {
14522 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14523 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14524 }
14525 }
14526 }
14527
14528 if( *cutoff )
14529 return SCIP_OKAY;
14530 if( tightened )
14531 {
14533 ++(*nfixedvars);
14534 else
14535 ++(*nchgbds);
14536
14537 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14538 for( v = 0; v < nvars; ++v )
14539 {
14540 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14541 SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14544 SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14545 }
14546 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14547
14548 for( v = 0; v < nvars; ++v )
14549 {
14550 if( v == bestindex )
14551 continue;
14552
14553 if( factor * vals[v] < 0 )
14554 {
14555 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14556 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14557 SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14558 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14559 }
14560 else
14561 {
14562 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14563 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14564 SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14565 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14566 }
14567
14568 if( *cutoff )
14569 return SCIP_OKAY;
14570 if( tightened )
14571 ++(*nfixedvars);
14572 }
14573 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14574 }
14575 }
14576 }
14577
14578 return SCIP_OKAY;
14579}
14580
14581/** applies full dual presolving on variables that only appear in linear constraints */
14582static
14584 SCIP* scip, /**< SCIP data structure */
14585 SCIP_CONS** conss, /**< constraint set */
14586 int nconss, /**< number of constraints */
14587 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14588 int* nchgbds, /**< pointer to count the number of bound changes */
14589 int* nchgvartypes /**< pointer to count the number of variable type changes */
14590 )
14591{
14592 SCIP_Real* redlb;
14593 SCIP_Real* redub;
14594 int* nlocksdown;
14595 int* nlocksup;
14596 SCIP_Bool* isimplint;
14597 SCIP_VAR** origvars;
14598 SCIP_VAR** vars;
14599 SCIP_VAR** conscontvars;
14600 int nvars;
14601 int nbinvars;
14602 int nintvars;
14603 int ncontvars;
14604 int v;
14605 int c;
14606
14607 /* we calculate redundancy bounds with the following meaning:
14608 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14609 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14610 * then:
14611 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14612 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14613 */
14614
14615 /* Additionally, we detect continuous variables that are implicitly integral.
14616 * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14617 * and all constraints (including the bounds as trivial constraints) in which:
14618 * c_j > 0: the variable is down-locked,
14619 * c_j < 0: the variable is up-locked,
14620 * c_j = 0: the variable appears
14621 * have, apart from j, only integer variables with integral coefficients and integral sides.
14622 * This is because then, the value of the variable is either determined by one of its bounds or
14623 * by one of these constraints, and in all cases, the value of the variable is integral.
14624 */
14625
14626 assert(scip != NULL);
14627 assert(nconss == 0 || conss != NULL);
14628 assert(nchgbds != NULL);
14629 assert(!SCIPinProbing(scip));
14630
14631 /* get active variables */
14632 nvars = SCIPgetNVars(scip);
14633 origvars = SCIPgetVars(scip);
14634
14635 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14636 nbinvars = SCIPgetNBinVars(scip);
14637 if( nbinvars == nvars )
14638 return SCIP_OKAY;
14639
14640 /* get number of continuous variables */
14641 ncontvars = SCIPgetNContVars(scip);
14642 nintvars = nvars - ncontvars;
14643
14644 /* copy the variable array since this array might change during the curse of this algorithm */
14645 nvars = nvars - nbinvars;
14646 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14647
14648 /* allocate temporary memory */
14649 SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14650 SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14651 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14652 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14653 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14654 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14655
14656 /* initialize redundancy bounds */
14657 for( v = 0; v < nvars; ++v )
14658 {
14659 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14660 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14661 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14662 }
14663 BMSclearMemoryArray(nlocksdown, nvars);
14664 BMSclearMemoryArray(nlocksup, nvars);
14665
14666 /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14667 * We better not use SCIPisFeasIntegral() in these checks.
14668 */
14669 for( v = 0; v < ncontvars; v++ )
14670 {
14671 SCIP_VAR* var;
14672 SCIP_Real obj;
14673 SCIP_Real lb;
14674 SCIP_Real ub;
14675
14676 var = vars[v + nintvars - nbinvars];
14677 lb = SCIPvarGetLbGlobal(var);
14678 ub = SCIPvarGetUbGlobal(var);
14679
14680 obj = SCIPvarGetObj(var);
14681 if( SCIPisZero(scip, obj) )
14682 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14683 else
14684 {
14685 if( SCIPisPositive(scip, obj) )
14686 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14687 else
14688 {
14689 assert(SCIPisNegative(scip, obj));
14690 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14691 }
14692 }
14693 }
14694
14695 /* scan all constraints */
14696 for( c = 0; c < nconss; ++c )
14697 {
14698 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14699 * part of checked disjunctions)
14700 */
14701 if( SCIPconsIsLocked(conss[c]) )
14702 {
14703 SCIP_CONSDATA* consdata;
14704 SCIP_Bool lhsexists;
14705 SCIP_Bool rhsexists;
14706 SCIP_Bool hasimpliedpotential;
14707 SCIP_Bool integralcoefs;
14708 int nlockspos;
14709 int contvarpos;
14710 int nconscontvars;
14711 int i;
14712
14713 consdata = SCIPconsGetData(conss[c]);
14714 assert(consdata != NULL);
14715
14716 /* get number of times the constraint was locked */
14717 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14718
14719 /* we do not want to include constraints with locked negation (this would be too weird) */
14720 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14721 {
14722 /* mark all continuous variables as not being implicit integral */
14723 for( i = 0; i < consdata->nvars; ++i )
14724 {
14725 SCIP_VAR* var;
14726
14727 var = consdata->vars[i];
14729 {
14730 int contv;
14731 contv = SCIPvarGetProbindex(var) - nintvars;
14732 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14733 isimplint[contv] = FALSE;
14734 }
14735 }
14736 continue;
14737 }
14738
14739 /* check for existing sides */
14740 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14741 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14742
14743 /* count locks and update redundancy bounds */
14744 contvarpos = -1;
14745 nconscontvars = 0;
14746 hasimpliedpotential = FALSE;
14747 integralcoefs = !SCIPconsIsModifiable(conss[c]);
14748
14749 for( i = 0; i < consdata->nvars; ++i )
14750 {
14751 SCIP_VAR* var;
14752 SCIP_Real val;
14753 SCIP_Real minresactivity;
14754 SCIP_Real maxresactivity;
14755 SCIP_Real newredlb;
14756 SCIP_Real newredub;
14757 SCIP_Bool ismintight;
14758 SCIP_Bool ismaxtight;
14759 SCIP_Bool isminsettoinfinity;
14760 SCIP_Bool ismaxsettoinfinity;
14761 int arrayindex;
14762
14763 var = consdata->vars[i];
14764 assert(var != NULL);
14765 val = consdata->vals[i];
14766 assert(!SCIPisZero(scip, val));
14767
14768 /* check if still all integer variables have integral coefficients */
14769 if( SCIPvarIsIntegral(var) )
14770 integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14771
14772 /* we do not need to process binary variables */
14773 if( SCIPvarIsBinary(var) )
14774 continue;
14775
14776 if( SCIPconsIsModifiable(conss[c]) )
14777 {
14778 minresactivity = -SCIPinfinity(scip);
14779 maxresactivity = SCIPinfinity(scip);
14780 isminsettoinfinity = TRUE;
14781 ismaxsettoinfinity = TRUE;
14782 }
14783 else
14784 {
14785 /* calculate residual activity bounds if variable would be fixed to zero */
14786 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14787 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
14788
14789 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14790 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14791 * This is needed, because we do not want to rely on relaxed finite resactivities.
14792 */
14793 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
14794
14795 /* check minresactivity for reliability */
14796 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14797 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14798
14799 /* check maxresactivity for reliability */
14800 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14801 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14802 }
14803
14804 arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14805
14806 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14807
14808 newredlb = redlb[arrayindex];
14809 newredub = redub[arrayindex];
14810 if( val > 0.0 )
14811 {
14812 if( lhsexists )
14813 {
14814 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14815 nlocksdown[arrayindex] += nlockspos;
14816 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14817 }
14818 if( rhsexists )
14819 {
14820 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14821 nlocksup[arrayindex] += nlockspos;
14822 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14823 }
14824 }
14825 else
14826 {
14827 if( lhsexists )
14828 {
14829 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14830 nlocksup[arrayindex] += nlockspos;
14831 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14832 }
14833 if( rhsexists )
14834 {
14835 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14836 nlocksdown[arrayindex] += nlockspos;
14837 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14838 }
14839 }
14840
14841 /* if the variable is integer, we have to round the value to the next integral value */
14842 if( SCIPvarIsIntegral(var) )
14843 {
14844 if( !SCIPisInfinity(scip, newredlb) )
14845 newredlb = SCIPceil(scip, newredlb);
14846 if( !SCIPisInfinity(scip, -newredub) )
14847 newredub = SCIPfloor(scip, newredub);
14848 }
14849
14850 /* update redundancy bounds */
14851 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14852 redub[arrayindex] = MIN(redub[arrayindex], newredub);
14853
14854 /* collect the continuous variables of the constraint */
14856 {
14857 int contv;
14858
14859 assert(nconscontvars < ncontvars);
14860 contvarpos = i;
14861 conscontvars[nconscontvars] = var;
14862 nconscontvars++;
14863
14864 contv = SCIPvarGetProbindex(var) - nintvars;
14865 assert(0 <= contv && contv < ncontvars);
14866 hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14867 }
14868 }
14869
14870 /* update implicit integer status of continuous variables */
14871 if( hasimpliedpotential )
14872 {
14873 if( nconscontvars > 1 || !integralcoefs )
14874 {
14875 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14876 * none of the continuous variables is implicit integer
14877 */
14878 for( i = 0; i < nconscontvars; i++ )
14879 {
14880 int contv;
14881 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14882 assert(0 <= contv && contv < ncontvars);
14883 isimplint[contv] = FALSE;
14884 }
14885 }
14886 else
14887 {
14888 SCIP_VAR* var;
14889 SCIP_Real val;
14890 SCIP_Real absval;
14891 int contv;
14892
14893 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14894 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14895 * side(s) of the constraint is integral
14896 */
14897 assert(nconscontvars == 1);
14898 assert(0 <= contvarpos && contvarpos < consdata->nvars);
14899 var = consdata->vars[contvarpos];
14900 val = consdata->vals[contvarpos];
14901 contv = SCIPvarGetProbindex(var) - nintvars;
14902 assert(0 <= contv && contv < ncontvars);
14903 assert(isimplint[contv]);
14904
14905 absval = REALABS(val);
14906 if( !SCIPisEQ(scip, absval, 1.0) )
14907 isimplint[contv] = FALSE;
14908 else
14909 {
14910 SCIP_Real obj;
14911
14912 obj = SCIPvarGetObj(var);
14913 if( obj * val >= 0.0 && lhsexists )
14914 {
14915 /* the variable may be blocked by the constraint's left hand side */
14916 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14917 }
14918 if( obj * val <= 0.0 && rhsexists )
14919 {
14920 /* the variable may be blocked by the constraint's left hand side */
14921 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14922 }
14923 }
14924 }
14925 }
14926 }
14927 }
14928
14929 /* check if any bounds can be tightened due to optimality */
14930 for( v = 0; v < nvars; ++v )
14931 {
14932 SCIP_VAR* var;
14933 SCIP_Real obj;
14934 SCIP_Bool infeasible;
14935 SCIP_Bool tightened;
14936
14937 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14938 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14939 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14940
14941 var = vars[v];
14942 obj = SCIPvarGetObj(var);
14943 if( !SCIPisPositive(scip, -obj) )
14944 {
14945 /* making the variable as small as possible does not increase the objective:
14946 * check if all down locks of the variables are due to linear constraints;
14947 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
14948 * constraints redundant is huge, we better do nothing for numerical reasons
14949 */
14951 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
14952 && !SCIPisHugeValue(scip, -redlb[v])
14953 && redlb[v] < SCIPvarGetUbGlobal(var) )
14954 {
14955 SCIP_Real ub;
14956
14957 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14958 * -> tighten upper bound to x_v <= redlb[v]
14959 */
14960 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14962 redlb[v]);
14963 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14964 assert(!infeasible);
14965
14966 ub = SCIPvarGetUbGlobal(var);
14967 redub[v] = MIN(redub[v], ub);
14968 if( tightened )
14969 (*nchgbds)++;
14970 }
14971 }
14972 if( !SCIPisPositive(scip, obj) )
14973 {
14974 /* making the variable as large as possible does not increase the objective:
14975 * check if all up locks of the variables are due to linear constraints;
14976 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
14977 * constraints redundant is huge, we better do nothing for numerical reasons
14978 */
14980 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
14981 && !SCIPisHugeValue(scip, redub[v])
14982 && redub[v] > SCIPvarGetLbGlobal(var) )
14983 {
14984 SCIP_Real lb;
14985
14986 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14987 * -> tighten lower bound to x_v >= redub[v]
14988 */
14989 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14991 redub[v]);
14992 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14993 assert(!infeasible);
14994
14995 lb = SCIPvarGetLbGlobal(var);
14996 redlb[v] = MAX(redlb[v], lb);
14997 if( tightened )
14998 (*nchgbds)++;
14999 }
15000 }
15001 }
15002
15003 /* upgrade continuous variables to implicit integers */
15004 for( v = nintvars - nbinvars; v < nvars; ++v )
15005 {
15006 SCIP_VAR* var;
15007 SCIP_Bool infeasible;
15008
15009 var = vars[v];
15010 assert(var != NULL);
15011
15013 assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15014 assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15015 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15016
15017 /* we can only conclude implicit integrality if the variable appears in no other constraint */
15018 if( isimplint[v - nintvars + nbinvars]
15019 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15020 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15021 {
15022 /* since we locally copied the variable array we can change the variable type immediately */
15023 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15024 (*nchgvartypes)++;
15025 if( infeasible )
15026 {
15027 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15028 *cutoff = TRUE;
15029
15030 break;
15031 }
15032
15033 SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15035 }
15036 }
15037
15038 /* free temporary memory */
15039 SCIPfreeBufferArray(scip, &conscontvars);
15040 SCIPfreeBufferArray(scip, &isimplint);
15041 SCIPfreeBufferArray(scip, &nlocksup);
15042 SCIPfreeBufferArray(scip, &nlocksdown);
15043 SCIPfreeBufferArray(scip, &redub);
15044 SCIPfreeBufferArray(scip, &redlb);
15045
15046 SCIPfreeBufferArray(scip, &vars);
15047
15048 return SCIP_OKAY;
15049}
15050
15051/** helper function to enforce constraints */
15052static
15054 SCIP* scip, /**< SCIP data structure */
15055 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15056 SCIP_CONS** conss, /**< constraints to process */
15057 int nconss, /**< number of constraints */
15058 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15059 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15060 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15061 )
15062{
15063 SCIP_CONSHDLRDATA* conshdlrdata;
15064 SCIP_Bool checkrelmaxabs;
15065 SCIP_Bool violated;
15066 SCIP_Bool cutoff = FALSE;
15067 int c;
15068
15069 assert(scip != NULL);
15070 assert(conshdlr != NULL);
15071 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15072 assert(result != NULL);
15073
15074 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15075 assert(conshdlrdata != NULL);
15076
15077 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15078
15079 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15080
15081 /* check for violated constraints
15082 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15083 */
15084 *result = SCIP_FEASIBLE;
15085
15086 /* check all useful linear constraints for feasibility */
15087 for( c = 0; c < nusefulconss; ++c )
15088 {
15089 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15090
15091 if( violated )
15092 {
15093 /* insert LP row as cut */
15094 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15095 if ( cutoff )
15096 *result = SCIP_CUTOFF;
15097 else
15098 *result = SCIP_SEPARATED;
15099 }
15100 }
15101
15102 /* check all obsolete linear constraints for feasibility */
15103 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15104 {
15105 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15106
15107 if( violated )
15108 {
15109 /* insert LP row as cut */
15110 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15111 if ( cutoff )
15112 *result = SCIP_CUTOFF;
15113 else
15114 *result = SCIP_SEPARATED;
15115 }
15116 }
15117
15118 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15119
15120 return SCIP_OKAY;
15121}
15122
15123/** adds symmetry information of constraint to a symmetry detection graph */
15124static
15126 SCIP* scip, /**< SCIP pointer */
15127 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15128 SCIP_CONS* cons, /**< constraint */
15129 SYM_GRAPH* graph, /**< symmetry detection graph */
15130 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15131 )
15132{
15133 SCIP_CONSDATA* consdata;
15134 SCIP_VAR** vars;
15135 SCIP_Real* vals;
15136 SCIP_Real constant = 0.0;
15137 SCIP_Real lhs;
15138 SCIP_Real rhs;
15139 int nlocvars;
15140 int nvars;
15141 int i;
15142
15143 assert(scip != NULL);
15144 assert(cons != NULL);
15145 assert(graph != NULL);
15146 assert(success != NULL);
15147
15148 consdata = SCIPconsGetData(cons);
15149 assert(consdata != NULL);
15150
15151 /* get active variables of the constraint */
15152 nvars = SCIPgetNVars(scip);
15153 nlocvars = consdata->nvars;
15154
15155 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
15156 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
15157
15158 for( i = 0; i < nlocvars; ++i )
15159 {
15160 vars[i] = consdata->vars[i];
15161 vals[i] = consdata->vals[i];
15162 }
15163
15164 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15165 lhs = consdata->lhs - constant;
15166 rhs = consdata->rhs - constant;
15167
15168 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15169 * of the same constraint are rated as equal
15170 */
15171 if ( SCIPisInfinity(scip, rhs) )
15172 {
15173 SCIP_Real tmp;
15174 assert(!SCIPisInfinity(scip, -lhs));
15175
15176 for( i = 0; i < nlocvars; ++i )
15177 vals[i] *= -1;
15178 tmp = rhs;
15179 rhs = -lhs;
15180 lhs = -tmp;
15181 }
15182
15183 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
15184 cons, lhs, rhs, success) );
15185
15186 SCIPfreeBufferArray(scip, &vals);
15187 SCIPfreeBufferArray(scip, &vars);
15188
15189 return SCIP_OKAY;
15190}
15191
15192/*
15193 * Callback methods of constraint handler
15194 */
15195
15196/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15197static
15198SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15199{ /*lint --e{715}*/
15200 assert(scip != NULL);
15201 assert(conshdlr != NULL);
15202 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15203
15204 /* call inclusion method of constraint handler */
15206
15207 *valid = TRUE;
15208
15209 return SCIP_OKAY;
15210}
15211
15212/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15213static
15214SCIP_DECL_CONSFREE(consFreeLinear)
15215{ /*lint --e{715}*/
15216 SCIP_CONSHDLRDATA* conshdlrdata;
15217
15218 assert(scip != NULL);
15219 assert(conshdlr != NULL);
15220 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15221
15222 /* free constraint handler data */
15223 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15224 assert(conshdlrdata != NULL);
15225
15226 conshdlrdataFree(scip, &conshdlrdata);
15227
15228 SCIPconshdlrSetData(conshdlr, NULL);
15229
15230 return SCIP_OKAY;
15231}
15232
15233
15234/** initialization method of constraint handler (called after problem was transformed) */
15235static
15236SCIP_DECL_CONSINIT(consInitLinear)
15237{
15238 SCIP_CONSHDLRDATA* conshdlrdata;
15239 int c;
15240
15241 assert(scip != NULL);
15242
15243 /* check for event handler */
15244 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15245 assert(conshdlrdata != NULL);
15246 assert(conshdlrdata->eventhdlr != NULL);
15247 assert(nconss == 0 || conss != NULL);
15248
15249 conshdlrdata->naddconss = 0;
15250
15251 /* catch events for the constraints */
15252 for( c = 0; c < nconss; ++c )
15253 {
15254 /* catch all events */
15255 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15256 }
15257
15258 return SCIP_OKAY;
15259}
15260
15261
15262/** deinitialization method of constraint handler (called before transformed problem is freed) */
15263static
15264SCIP_DECL_CONSEXIT(consExitLinear)
15265{
15266 SCIP_CONSHDLRDATA* conshdlrdata;
15267 int c;
15268
15269 assert(scip != NULL);
15270
15271 /* check for event handler */
15272 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15273 assert(conshdlrdata != NULL);
15274 assert(conshdlrdata->eventhdlr != NULL);
15275
15276 /* drop events for the constraints */
15277 for( c = nconss - 1; c >= 0; --c )
15278 {
15279 SCIP_CONSDATA* consdata;
15280
15281 consdata = SCIPconsGetData(conss[c]);
15282 assert(consdata != NULL);
15283
15284 if( consdata->eventdata != NULL )
15285 {
15286 /* drop all events */
15287 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15288 assert(consdata->eventdata == NULL);
15289 }
15290 }
15291
15292 return SCIP_OKAY;
15293}
15294
15295/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15296static
15298 SCIP* scip, /**< SCIP data structure */
15299 SCIP_Real lhs, /**< left hand side */
15300 SCIP_Real rhs /**< right hand side */
15301 )
15302{
15303 assert(scip != NULL);
15304
15305 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15306}
15307
15308/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15309static
15311 SCIP* scip, /**< SCIP data structure */
15312 SCIP_Real x /**< value */
15313 )
15314{
15315 assert(scip != NULL);
15316
15317 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15318}
15319
15320/** performs linear constraint type classification as used for MIPLIB
15321 *
15322 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15323 *
15324 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15325 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15326 * Similarly, if specialized constraints were created through the API, these are currently not present.
15327 */
15329 SCIP* scip, /**< SCIP data structure */
15330 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15331 )
15332{
15333 int c;
15334 SCIP_CONSHDLR* conshdlr;
15335 SCIP_CONS** conss;
15336 int nconss;
15337
15338 assert(scip != NULL);
15339 assert(linconsstats != NULL);
15340 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15341 assert(conshdlr != NULL);
15342
15344 {
15345 conss = SCIPgetConss(scip);
15346 nconss = SCIPgetNConss(scip);
15347 }
15348 else
15349 {
15350 conss = SCIPconshdlrGetConss(conshdlr);
15351 nconss = SCIPconshdlrGetNConss(conshdlr);
15352 }
15353
15354 /* reset linear constraint type classification */
15355 SCIPlinConsStatsReset(linconsstats);
15356
15357 /* loop through all constraints */
15358 for( c = 0; c < nconss; c++ )
15359 {
15360 SCIP_CONS* cons;
15361 SCIP_CONSDATA* consdata;
15362 SCIP_Real lhs;
15363 SCIP_Real rhs;
15364 int i;
15365
15366 /* get constraint */
15367 cons = conss[c];
15368 assert(cons != NULL);
15369
15370 /* skip constraints that are not handled by the constraint handler */
15371 if( SCIPconsGetHdlr(cons) != conshdlr )
15372 continue;
15373
15374 /* get constraint data */
15375 consdata = SCIPconsGetData(cons);
15376 assert(consdata != NULL);
15377 rhs = consdata->rhs;
15378 lhs = consdata->lhs;
15379
15380 /* merge multiples and delete variables with zero coefficient */
15381 SCIP_CALL( mergeMultiples(scip, cons) );
15382 for( i = 0; i < consdata->nvars; i++ )
15383 {
15384 assert(!SCIPisZero(scip, consdata->vals[i]));
15385 }
15386
15387 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15388 if( consdata->nvars == 0 )
15389 {
15390 SCIPdebugMsg(scip, "classified as EMPTY: ");
15393
15394 continue;
15395 }
15396
15397 /* is constraint of type SCIP_CONSTYPE_FREE? */
15398 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15399 {
15400 SCIPdebugMsg(scip, "classified as FREE: ");
15403
15404 continue;
15405 }
15406
15407 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15408 if( consdata->nvars == 1 )
15409 {
15410 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15413
15414 continue;
15415 }
15416
15417 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15418 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15419 {
15420 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15423
15424 continue;
15425 }
15426
15427 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15428 if( consdata->nvars == 2 )
15429 {
15430 SCIP_LINCONSTYPE constype;
15431
15432 /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15433 if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15434 && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15435 {
15436 constype = SCIP_LINCONSTYPE_PRECEDENCE;
15437 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15438 }
15439 else
15440 {
15441 constype = SCIP_LINCONSTYPE_VARBOUND;
15442 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15443 }
15445
15446 SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15447
15448 continue;
15449 }
15450
15451 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15452 {
15453 SCIP_Real scale;
15454 SCIP_Real b;
15455 SCIP_Bool unmatched;
15456 int nnegbinvars;
15457
15458 unmatched = FALSE;
15459 nnegbinvars = 0;
15460
15461 scale = REALABS(consdata->vals[0]);
15462
15463 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15464 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15465 {
15466 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15467 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15468 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15469 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15470
15471 if( consdata->vals[i] < 0.0 )
15472 nnegbinvars++;
15473 }
15474
15475 if( !unmatched )
15476 {
15477 if( SCIPisEQ(scip, lhs, rhs) )
15478 {
15479 b = rhs/scale + nnegbinvars;
15480 if( SCIPisEQ(scip, 1.0, b) )
15481 {
15482 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15485
15486 continue;
15487 }
15488 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15489 {
15490 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15493
15494 continue;
15495 }
15496 }
15497
15498 /* compute right hand side divided by scale */
15499 if( !SCIPisInfinity(scip, rhs) )
15500 b = rhs/scale + nnegbinvars;
15501 else
15502 b = SCIPinfinity(scip);
15503
15504 if( SCIPisEQ(scip, 1.0, b) )
15505 {
15506 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15509
15510 /* relax right hand side to prevent further classifications */
15511 rhs = SCIPinfinity(scip);
15512 }
15513 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15514 {
15515 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15517
15519
15520 /* relax right hand side to prevent further classifications */
15521 rhs = SCIPinfinity(scip);
15522 }
15523
15524 if( !SCIPisInfinity(scip, lhs) )
15525 b = lhs/scale + nnegbinvars;
15526 else
15527 b = SCIPinfinity(scip);
15528
15529 if( SCIPisEQ(scip, 1.0, b) )
15530 {
15531 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15534
15535 /* relax left hand side to prevent further classifications */
15536 lhs = -SCIPinfinity(scip);
15537 }
15538
15539 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15540 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15541 continue;
15542 }
15543 }
15544
15545 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15546 /* @todo If coefficients or rhs are not integral, we currently do not check
15547 * if the constraint could be scaled (finitely), such that they are.
15548 */
15549 {
15550 SCIP_Real b;
15551 SCIP_Bool unmatched;
15552
15553 b = rhs;
15554 unmatched = FALSE;
15555 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15556 {
15557 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15558 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15559 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15560 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15561
15562 if( SCIPisNegative(scip, consdata->vals[i]) )
15563 b -= consdata->vals[i];
15564 }
15565 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15566
15567 if( !unmatched )
15568 {
15569 if( SCIPisEQ(scip, lhs, rhs) )
15570 {
15571 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15573
15575
15576 continue;
15577 }
15578 else
15579 {
15580 SCIP_Bool matched;
15581
15582 matched = FALSE;
15583 for( i = 0; i < consdata->nvars && !matched; i++ )
15584 {
15585 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15586 }
15587
15588 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15591 }
15592
15593 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15594 if( SCIPisInfinity(scip, -lhs) )
15595 continue;
15596 else
15597 rhs = SCIPinfinity(scip);
15598 }
15599 }
15600
15601 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15602 {
15603 SCIP_Real b;
15604 SCIP_Bool unmatched;
15605
15606 unmatched = FALSE;
15607
15608 b = rhs;
15609 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15610
15611 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15612 {
15613 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15614 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15615 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15616 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15617 }
15618
15619 if( !unmatched )
15620 {
15621 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15624
15625 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15626 if( SCIPisInfinity(scip, -lhs) )
15627 continue;
15628 else
15629 rhs = SCIPinfinity(scip);
15630 }
15631 }
15632
15633 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15634 {
15635 SCIP_Bool unmatched;
15636
15637 unmatched = FALSE;
15638 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15639 {
15640 if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15641 && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15642 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15643 unmatched = TRUE;
15644 }
15645
15646 if( !unmatched )
15647 {
15648 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15651
15652 continue;
15653 }
15654 }
15655
15656 /* no special structure detected */
15657 SCIPdebugMsg(scip, "classified as GENERAL: ");
15659 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15660 }
15661
15662 return SCIP_OKAY;
15663}
15664
15665
15666/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15667static
15668SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15669{ /*lint --e{715}*/
15670 int c;
15671#ifdef SCIP_STATISTIC
15672 SCIP_CONSHDLRDATA* conshdlrdata;
15673 int ngoodconss;
15674 int nallconss;
15675#endif
15676
15677 /* delete all linear constraints that were upgraded to a more specific constraint type;
15678 * make sure, only active variables remain in the remaining constraints
15679 */
15680 assert(scip != NULL);
15681
15682#ifdef SCIP_STATISTIC
15683 /* count number of well behaved linear constraints */
15684 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15685 assert(conshdlrdata != NULL);
15686
15687 ngoodconss = 0;
15688 nallconss = 0;
15689
15690 for( c = 0; c < nconss; ++c )
15691 {
15692 SCIP_CONSDATA* consdata;
15693
15694 if( SCIPconsIsDeleted(conss[c]) )
15695 continue;
15696
15697 consdata = SCIPconsGetData(conss[c]);
15698 assert(consdata != NULL);
15699
15700 if( consdata->upgraded )
15701 continue;
15702
15703 nallconss++;
15704
15706
15707 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15708 ngoodconss++;
15709 }
15710 if( nallconss )
15711 {
15712 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15713 }
15714#endif
15715
15716 for( c = 0; c < nconss; ++c )
15717 {
15718 SCIP_CONSDATA* consdata;
15719
15720 if( SCIPconsIsDeleted(conss[c]) )
15721 continue;
15722
15723 consdata = SCIPconsGetData(conss[c]);
15724 assert(consdata != NULL);
15725
15726 if( consdata->upgraded )
15727 {
15728 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15729 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15730 */
15731 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15732 }
15733 else
15734 {
15735 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15736 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15737 }
15738 }
15739
15740 return SCIP_OKAY;
15741}
15742
15743/** solving process initialization method of constraint handler */
15744static
15745SCIP_DECL_CONSINITSOL(consInitsolLinear)
15746{ /*lint --e{715}*/
15747 /* add nlrow representation to NLP, if NLP had been constructed */
15749 {
15750 int c;
15751 for( c = 0; c < nconss; ++c )
15752 {
15753 SCIP_CALL( addNlrow(scip, conss[c]) );
15754 }
15755 }
15756
15757 return SCIP_OKAY;
15758}
15759
15760/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15761static
15762SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15763{ /*lint --e{715}*/
15764 int c;
15765
15766 assert(scip != NULL);
15767
15768 /* release the rows and nlrows of all constraints */
15769 for( c = 0; c < nconss; ++c )
15770 {
15771 SCIP_CONSDATA* consdata;
15772
15773 consdata = SCIPconsGetData(conss[c]);
15774 assert(consdata != NULL);
15775
15776 if( consdata->row != NULL )
15777 {
15778 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15779 }
15780
15781 if( consdata->nlrow != NULL )
15782 {
15783 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15784 }
15785 }
15786
15787 /* if this is a restart, convert cutpool rows into linear constraints */
15788 if( restart )
15789 {
15790 int ncutsadded;
15791
15792 ncutsadded = 0;
15793
15794 /* create out of all active cuts in cutpool linear constraints */
15795 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15796
15797 if( ncutsadded > 0 )
15798 {
15800 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15801 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15802 * line correctly
15803 */
15805 }
15806 }
15807
15808 return SCIP_OKAY;
15809}
15810
15811
15812/** constraint activation notification method of constraint handler */
15813static
15814SCIP_DECL_CONSACTIVE(consActiveLinear)
15815{ /*lint --e{715}*/
15816 assert(cons != NULL);
15817
15819 {
15820 SCIP_CALL( addNlrow(scip, cons) );
15821 }
15822
15823 return SCIP_OKAY;
15824}
15825
15826/** constraint deactivation notification method of constraint handler */
15827static
15828SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15829{ /*lint --e{715}*/
15830 SCIP_CONSDATA* consdata;
15831
15832 assert(scip != NULL);
15833 assert(conshdlr != NULL);
15834 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15835 assert(cons != NULL );
15836
15837 /* get constraint data */
15838 consdata = SCIPconsGetData(cons);
15839 assert(consdata != NULL);
15840
15841 if( SCIPconsIsDeleted(cons) )
15842 {
15843 SCIP_CONSHDLRDATA* conshdlrdata;
15844
15845 /* check for event handler */
15846 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15847 assert(conshdlrdata != NULL);
15848 assert(conshdlrdata->eventhdlr != NULL);
15849
15850 /* free event data */
15851 if( consdata->eventdata != NULL )
15852 {
15853 /* drop bound change events of variables */
15854 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15855 }
15856 assert(consdata->eventdata == NULL);
15857 }
15858
15859 /* remove row from NLP, if still in solving
15860 * if we are in exitsolve, the whole NLP will be freed anyway
15861 */
15862 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15863 {
15864 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15865 }
15866
15867 return SCIP_OKAY;
15868}
15869
15870
15871/** frees specific constraint data */
15872static
15873SCIP_DECL_CONSDELETE(consDeleteLinear)
15874{ /*lint --e{715}*/
15875 assert(scip != NULL);
15876 assert(conshdlr != NULL);
15877 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15878
15879 if( (*consdata)->eventdata != NULL )
15880 {
15881 SCIP_CONSHDLRDATA* conshdlrdata;
15882
15883 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15884 assert(conshdlrdata != NULL);
15885
15886 /* drop all events */
15887 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15888 assert((*consdata)->eventdata == NULL);
15889 }
15890
15891 /* free linear constraint */
15892 SCIP_CALL( consdataFree(scip, consdata) );
15893
15894 return SCIP_OKAY;
15895}
15896
15897
15898/** transforms constraint data into data belonging to the transformed problem */
15899static
15900SCIP_DECL_CONSTRANS(consTransLinear)
15901{ /*lint --e{715}*/
15902 SCIP_CONSDATA* sourcedata;
15903 SCIP_CONSDATA* targetdata;
15904
15905 /*debugMsg(scip, "Trans method of linear constraints\n");*/
15906
15907 assert(scip != NULL);
15908 assert(conshdlr != NULL);
15909 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15911 assert(sourcecons != NULL);
15912 assert(targetcons != NULL);
15913
15914 sourcedata = SCIPconsGetData(sourcecons);
15915 assert(sourcedata != NULL);
15916 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15917
15918 /* create linear constraint data for target constraint */
15919 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15920
15921#ifndef NDEBUG
15922 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15923 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15924 {
15925 int n;
15926 for(n = targetdata->nvars - 1; n >= 0; --n )
15927 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15928 }
15929#endif
15930
15931 /* create target constraint */
15932 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15933 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15934 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15935 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15936 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15937
15938 return SCIP_OKAY;
15939}
15940
15941
15942/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15943static
15944SCIP_DECL_CONSINITLP(consInitlpLinear)
15945{ /*lint --e{715}*/
15946 int c;
15947
15948 assert(scip != NULL);
15949 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15950
15951 *infeasible = FALSE;
15952
15953 for( c = 0; c < nconss && !(*infeasible); ++c )
15954 {
15955 assert(SCIPconsIsInitial(conss[c]));
15956 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15957 }
15958
15959 return SCIP_OKAY;
15960}
15961
15962
15963/** separation method of constraint handler for LP solutions */
15964static
15965SCIP_DECL_CONSSEPALP(consSepalpLinear)
15966{ /*lint --e{715}*/
15967 SCIP_CONSHDLRDATA* conshdlrdata;
15968 SCIP_Real loclowerbound;
15969 SCIP_Real glblowerbound;
15970 SCIP_Real cutoffbound;
15971 SCIP_Real maxbound;
15972 SCIP_Bool separatecards;
15973 SCIP_Bool cutoff;
15974 int c;
15975 int depth;
15976 int nrounds;
15977 int maxsepacuts;
15978 int ncuts;
15979
15980 assert(scip != NULL);
15981 assert(conshdlr != NULL);
15982 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15983 assert(result != NULL);
15984
15985 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15986 assert(conshdlrdata != NULL);
15987 depth = SCIPgetDepth(scip);
15988 nrounds = SCIPgetNSepaRounds(scip);
15989
15990 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15991
15992 *result = SCIP_DIDNOTRUN;
15993
15994 /* only call the separator a given number of times at each node */
15995 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15996 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15997 return SCIP_OKAY;
15998
15999 /* get the maximal number of cuts allowed in a separation round */
16000 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16001
16002 /* check if we want to produce knapsack cardinality cuts at this node */
16003 loclowerbound = SCIPgetLocalLowerbound(scip);
16004 glblowerbound = SCIPgetLowerbound(scip);
16005 cutoffbound = SCIPgetCutoffbound(scip);
16006 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16007 separatecards = SCIPisLE(scip, loclowerbound, maxbound);
16008 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
16009
16010 *result = SCIP_DIDNOTFIND;
16011 ncuts = 0;
16012 cutoff = FALSE;
16013
16014 /* check all useful linear constraints for feasibility */
16015 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16016 {
16017 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16018 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16019 }
16020
16021 /* adjust return value */
16022 if( cutoff )
16023 *result = SCIP_CUTOFF;
16024 else if( ncuts > 0 )
16025 *result = SCIP_SEPARATED;
16026
16027 /* combine linear constraints to get more cuts */
16028 /**@todo further cuts of linear constraints */
16029
16030 return SCIP_OKAY;
16031}
16032
16033
16034/** separation method of constraint handler for arbitrary primal solutions */
16035static
16036SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16037{ /*lint --e{715}*/
16038 SCIP_CONSHDLRDATA* conshdlrdata;
16039 int c;
16040 int depth;
16041 int nrounds;
16042 int maxsepacuts;
16043 int ncuts;
16044 SCIP_Bool cutoff;
16045
16046 assert(scip != NULL);
16047 assert(conshdlr != NULL);
16048 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16049 assert(result != NULL);
16050
16051 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16052 assert(conshdlrdata != NULL);
16053 depth = SCIPgetDepth(scip);
16054 nrounds = SCIPgetNSepaRounds(scip);
16055
16056 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16057
16058 *result = SCIP_DIDNOTRUN;
16059
16060 /* only call the separator a given number of times at each node */
16061 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16062 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16063 return SCIP_OKAY;
16064
16065 /* get the maximal number of cuts allowed in a separation round */
16066 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16067
16068 *result = SCIP_DIDNOTFIND;
16069 ncuts = 0;
16070 cutoff = FALSE;
16071
16072 /* check all useful linear constraints for feasibility */
16073 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16074 {
16075 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16076 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16077 }
16078
16079 /* adjust return value */
16080 if( cutoff )
16081 *result = SCIP_CUTOFF;
16082 else if( ncuts > 0 )
16083 *result = SCIP_SEPARATED;
16084
16085 /* combine linear constraints to get more cuts */
16086 /**@todo further cuts of linear constraints */
16087
16088 return SCIP_OKAY;
16089}
16090
16091
16092/** constraint enforcing method of constraint handler for LP solutions */
16093static
16094SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16095{ /*lint --e{715}*/
16096 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16097
16098 return SCIP_OKAY;
16099}
16100
16101/** constraint enforcing method of constraint handler for relaxation solutions */
16102static
16103SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16104{ /*lint --e{715}*/
16105 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16106
16107 return SCIP_OKAY;
16108}
16109
16110/** constraint enforcing method of constraint handler for pseudo solutions */
16111static
16112SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16113{ /*lint --e{715}*/
16114 SCIP_CONSHDLRDATA* conshdlrdata;
16115 SCIP_Bool checkrelmaxabs;
16116 SCIP_Bool violated;
16117 int c;
16118
16119 assert(scip != NULL);
16120 assert(conshdlr != NULL);
16121 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16122 assert(result != NULL);
16123
16124 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16125 assert(conshdlrdata != NULL);
16126
16127 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16128
16129 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16130
16131 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16132 if( objinfeasible )
16133 {
16134 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16135
16136 *result = SCIP_DIDNOTRUN;
16137 return SCIP_OKAY;
16138 }
16139
16140 /* check all linear constraints for feasibility */
16141 violated = FALSE;
16142 for( c = 0; c < nconss && !violated; ++c )
16143 {
16144 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16145 }
16146
16147 if( violated )
16148 *result = SCIP_INFEASIBLE;
16149 else
16150 *result = SCIP_FEASIBLE;
16151
16152 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16153
16154 return SCIP_OKAY;
16155}
16156
16157
16158/** feasibility check method of constraint handler for integral solutions */
16159static
16160SCIP_DECL_CONSCHECK(consCheckLinear)
16161{ /*lint --e{715}*/
16162 SCIP_CONSHDLRDATA* conshdlrdata;
16163 SCIP_Bool checkrelmaxabs;
16164 int c;
16165
16166 assert(scip != NULL);
16167 assert(conshdlr != NULL);
16168 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16169 assert(result != NULL);
16170
16171 *result = SCIP_FEASIBLE;
16172
16173 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16174 assert(conshdlrdata != NULL);
16175
16176 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16177
16178 /*debugMsg(scip, "Check method of linear constraints\n");*/
16179
16180 /* check all linear constraints for feasibility */
16181 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16182 {
16183 SCIP_Bool violated = FALSE;
16184 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16185
16186 if( violated )
16187 {
16188 *result = SCIP_INFEASIBLE;
16189
16190 if( printreason )
16191 {
16192 SCIP_CONSDATA* consdata;
16193 SCIP_Real activity;
16194
16195 consdata = SCIPconsGetData(conss[c]);
16196 assert( consdata != NULL);
16197
16198 activity = consdataGetActivity(scip, consdata, sol);
16199
16200 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16201 SCIPinfoMessage(scip, NULL, ";\n");
16202
16203 if( activity == SCIP_INVALID ) /*lint !e777*/
16204 SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16205 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16206 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16207 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16208 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16209 }
16210 }
16211 }
16212
16213 return SCIP_OKAY;
16214}
16215
16216
16217/** domain propagation method of constraint handler */
16218static
16219SCIP_DECL_CONSPROP(consPropLinear)
16220{ /*lint --e{715}*/
16221 SCIP_CONSHDLRDATA* conshdlrdata;
16222 SCIP_Bool rangedrowpropagation = FALSE;
16223 SCIP_Bool tightenbounds;
16224 SCIP_Bool cutoff;
16225
16226 int nchgbds;
16227 int i;
16228
16229 assert(scip != NULL);
16230 assert(conshdlr != NULL);
16231 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16232 assert(result != NULL);
16233
16234 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16235 assert(conshdlrdata != NULL);
16236
16237 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16238
16239 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16240 if( SCIPinProbing(scip) )
16241 tightenbounds = TRUE;
16242 else
16243 {
16244 int depth;
16245 int propfreq;
16246 int tightenboundsfreq;
16247 int rangedrowfreq;
16248
16249 depth = SCIPgetDepth(scip);
16250 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16251 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16252 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16253 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16254
16255 /* check if we want to do ranged row propagation */
16256 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16257 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16258 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16259 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16260 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16261 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16262 }
16263
16264 cutoff = FALSE;
16265 nchgbds = 0;
16266
16267 /* process constraints marked for propagation */
16268 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16269 {
16271 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16272 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16273 }
16274
16275 /* adjust result code */
16276 if( cutoff )
16277 *result = SCIP_CUTOFF;
16278 else if( nchgbds > 0 )
16279 *result = SCIP_REDUCEDDOM;
16280 else
16281 *result = SCIP_DIDNOTFIND;
16282
16283 return SCIP_OKAY;
16284}
16285
16286
16287#define MAXCONSPRESOLROUNDS 10
16288/** presolving method of constraint handler */
16289static
16290SCIP_DECL_CONSPRESOL(consPresolLinear)
16291{ /*lint --e{715}*/
16292 SCIP_CONSHDLRDATA* conshdlrdata;
16293 SCIP_CONS* cons;
16294 SCIP_CONSDATA* consdata;
16295 SCIP_Real minactivity;
16296 SCIP_Real maxactivity;
16297 SCIP_Bool isminacttight;
16298 SCIP_Bool ismaxacttight;
16299 SCIP_Bool isminsettoinfinity;
16300 SCIP_Bool ismaxsettoinfinity;
16301 SCIP_Bool cutoff;
16302 int oldnfixedvars;
16303 int oldnaggrvars;
16304 int oldnchgbds;
16305 int oldndelconss;
16306 int oldnupgdconss;
16307 int oldnchgcoefs;
16308 int oldnchgsides;
16309 int firstchange;
16310 int firstupgradetry;
16311 int c;
16312
16313 assert(scip != NULL);
16314 assert(conshdlr != NULL);
16315 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16316 assert(result != NULL);
16317
16318 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16319
16320 /* remember old preprocessing counters */
16321 cutoff = FALSE;
16322 oldnfixedvars = *nfixedvars;
16323 oldnaggrvars = *naggrvars;
16324 oldnchgbds = *nchgbds;
16325 oldndelconss = *ndelconss;
16326 oldnupgdconss = *nupgdconss;
16327 oldnchgcoefs = *nchgcoefs;
16328 oldnchgsides = *nchgsides;
16329
16330 /* get constraint handler data */
16331 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16332 assert(conshdlrdata != NULL);
16333
16334 /* process single constraints */
16335 firstchange = INT_MAX;
16336 firstupgradetry = INT_MAX;
16337 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16338 {
16339 int npresolrounds;
16340 SCIP_Bool infeasible;
16341
16342 infeasible = FALSE;
16343
16344 cons = conss[c];
16345 assert(SCIPconsIsActive(cons));
16346 consdata = SCIPconsGetData(cons);
16347 assert(consdata != NULL);
16348
16349 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16350 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16351 {
16352 consdata->lhs = consdata->rhs;
16353 assert(consdata->row == NULL);
16354 }
16355
16356 if( consdata->eventdata == NULL )
16357 {
16358 /* catch bound change events of variables */
16359 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16360 assert(consdata->eventdata != NULL);
16361 }
16362
16363 /* constraint should not be already presolved in the initial round */
16364 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16365 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16366 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16367 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16368
16369 /* incorporate fixings and aggregations in constraint */
16370 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16371
16372 if( infeasible )
16373 {
16374 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16375 cutoff = TRUE;
16376 break;
16377 }
16378
16379 assert(consdata->removedfixings);
16380
16381 /* we can only presolve linear constraints, that are not modifiable */
16382 if( SCIPconsIsModifiable(cons) )
16383 continue;
16384
16385 /* remember the first changed constraint to begin the next aggregation round with */
16386 if( firstchange == INT_MAX && consdata->changed )
16387 firstchange = c;
16388
16389 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16390 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16391 firstupgradetry = c;
16392
16393 /* check, if constraint is already preprocessed */
16394 if( consdata->presolved )
16395 continue;
16396
16397 assert(SCIPconsIsActive(cons));
16398
16399 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16401
16402 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16403 * to avoid nearly infinite cycling due to very small bound changes)
16404 */
16405 npresolrounds = 0;
16406 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16407 {
16408 assert(!cutoff);
16409 npresolrounds++;
16410
16411 /* mark constraint being presolved and propagated */
16412 consdata->presolved = TRUE;
16414
16415 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16416
16417 if( infeasible )
16418 {
16419 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16420 cutoff = TRUE;
16421 break;
16422 }
16423
16424 /* tighten left and right hand side due to integrality */
16425 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16426
16427 if( infeasible )
16428 {
16429 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16430 cutoff = TRUE;
16431 break;
16432 }
16433
16434 /* check bounds */
16435 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16436 {
16437 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16438 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16439 cutoff = TRUE;
16440 break;
16441 }
16442
16443 /* tighten variable's bounds */
16444 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16445 if( cutoff )
16446 break;
16447
16448 /* check for fixed variables */
16449 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16450 if( cutoff )
16451 break;
16452
16453 /* check constraint for infeasibility and redundancy */
16454 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
16455 &isminsettoinfinity, &ismaxsettoinfinity);
16456 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16457 {
16458 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16459 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16460 cutoff = TRUE;
16461 break;
16462 }
16463 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16464 {
16465 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16466 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16467 SCIP_CALL( SCIPdelCons(scip, cons) );
16468 assert(!SCIPconsIsActive(cons));
16469
16470 if( !consdata->upgraded )
16471 (*ndelconss)++;
16472 break;
16473 }
16474 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16475 {
16476 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16477 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16478 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16479 if( !consdata->upgraded )
16480 (*nchgsides)++;
16481 }
16482 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16483 {
16484 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16485 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16487 if( !consdata->upgraded )
16488 (*nchgsides)++;
16489 }
16490
16491 /* handle empty constraint */
16492 if( consdata->nvars == 0 )
16493 {
16494 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16495 {
16496 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16497 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16498 cutoff = TRUE;
16499 }
16500 else
16501 {
16502 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16503 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16504 SCIP_CALL( SCIPdelCons(scip, cons) );
16505 assert(!SCIPconsIsActive(cons));
16506
16507 if( !consdata->upgraded )
16508 (*ndelconss)++;
16509 }
16510 break;
16511 }
16512
16513 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16514 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16515
16516 /* try to simplify inequalities */
16517 if( conshdlrdata->simplifyinequalities )
16518 {
16519 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16520
16521 if( cutoff )
16522 break;
16523 }
16524
16525 /* aggregation variable in equations */
16526 if( conshdlrdata->aggregatevariables )
16527 {
16528 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16529 if( cutoff )
16530 break;
16531 }
16532 }
16533
16534 if( !cutoff && !SCIPisStopped(scip) )
16535 {
16536 /* perform ranged row propagation */
16537 if( conshdlrdata->rangedrowpropagation )
16538 {
16539 int lastnfixedvars;
16540
16541 lastnfixedvars = *nfixedvars;
16542
16543 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16544 if( !cutoff )
16545 {
16546 if( lastnfixedvars < *nfixedvars )
16547 {
16548 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16549 }
16550 }
16551 }
16552
16553 /* extract cliques from constraint */
16554 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16555 {
16556 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16557 nfixedvars, nchgbds, &cutoff) );
16558
16559 /* check if the constraint got redundant or infeasible */
16560 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16561 {
16562 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16563 {
16564 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16565 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16566 cutoff = TRUE;
16567 }
16568 else
16569 {
16570 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16571 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16572 SCIP_CALL( SCIPdelCons(scip, cons) );
16573 assert(!SCIPconsIsActive(cons));
16574
16575 if( !consdata->upgraded )
16576 (*ndelconss)++;
16577 }
16578 }
16579 }
16580
16581 /* convert special equalities */
16582 if( !cutoff && SCIPconsIsActive(cons) )
16583 {
16584 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16585 }
16586
16587 /* apply dual presolving for variables that appear in only one constraint */
16588 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16589 {
16590 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16591 }
16592
16593 /* check if an inequality is parallel to the objective function */
16594 if( !cutoff && SCIPconsIsActive(cons) )
16595 {
16596 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16597 }
16598
16599 /* remember the first changed constraint to begin the next aggregation round with */
16600 if( firstchange == INT_MAX && consdata->changed )
16601 firstchange = c;
16602
16603 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16604 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16605 firstupgradetry = c;
16606 }
16607
16608 /* singleton column stuffing */
16609 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16610 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16611 {
16612 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16613 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16614
16615 /* handle empty constraint */
16616 if( consdata->nvars == 0 )
16617 {
16618 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16619 {
16620 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16621 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16622 cutoff = TRUE;
16623 }
16624 else
16625 {
16626 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16627 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16628 SCIP_CALL( SCIPdelCons(scip, cons) );
16629 assert(!SCIPconsIsActive(cons));
16630
16631 if( !consdata->upgraded )
16632 (*ndelconss)++;
16633 }
16634 break;
16635 }
16636 }
16637 }
16638
16639 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16640 * only apply this expensive procedure in exhaustive presolving timing
16641 */
16642 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16643 {
16644 assert(firstchange >= 0);
16645
16646 if( firstchange < nconss && conshdlrdata->presolusehashing )
16647 {
16648 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16649 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16650 ndelconss, nchgsides) );
16651 }
16652
16653 if( firstchange < nconss && conshdlrdata->presolpairwise )
16654 {
16655 SCIP_CONS** usefulconss;
16656 int nusefulconss;
16657 int firstchangenew;
16658 SCIP_Longint npaircomparisons;
16659
16660 npaircomparisons = 0;
16661 oldndelconss = *ndelconss;
16662 oldnchgsides = *nchgsides;
16663 oldnchgcoefs = *nchgcoefs;
16664
16665 /* allocate temporary memory */
16666 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16667
16668 nusefulconss = 0;
16669 firstchangenew = -1;
16670 for( c = 0; c < nconss; ++c )
16671 {
16672 /* update firstchange */
16673 if( c == firstchange )
16674 firstchangenew = nusefulconss;
16675
16676 /* ignore inactive and modifiable constraints */
16677 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16678 continue;
16679
16680 usefulconss[nusefulconss] = conss[c];
16681 ++nusefulconss;
16682 }
16683 firstchange = firstchangenew;
16684 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16685
16686 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16687 {
16688 /* constraint has become inactive or modifiable during pairwise presolving */
16689 if( usefulconss[c] == NULL )
16690 continue;
16691
16692 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16693
16694 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16695 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16696 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16697
16698 if( npaircomparisons > conshdlrdata->nmincomparisons )
16699 {
16700 assert(npaircomparisons > 0);
16701 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16702 break;
16703 oldndelconss = *ndelconss;
16704 oldnchgsides = *nchgsides;
16705 oldnchgcoefs = *nchgcoefs;
16706 npaircomparisons = 0;
16707 }
16708 }
16709 /* free temporary memory */
16710 SCIPfreeBufferArray(scip, &usefulconss);
16711 }
16712 }
16713
16714 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16715 * in linear constraints and we therefore have full information about it
16716 */
16717 if( !cutoff && firstupgradetry < nconss
16718 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16719 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16720 )
16721 {
16722 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16723 {
16724 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds, nchgvartypes) );
16725 }
16726 }
16727
16728 /* try to upgrade constraints into a more specific constraint type;
16729 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16730 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16731 */
16732 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16733 {
16734 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16735 {
16736 cons = conss[c];
16737
16738 /* don't upgrade modifiable constraints */
16739 if( SCIPconsIsModifiable(cons) )
16740 continue;
16741
16742 consdata = SCIPconsGetData(cons);
16743 assert(consdata != NULL);
16744
16745 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16746 if( consdata->upgradetried )
16747 continue;
16748 /* @todo force that upgrade will be performed later? */
16749 if( !consdata->presolved )
16750 continue;
16751
16752 consdata->upgradetried = TRUE;
16753 if( SCIPconsIsActive(cons) )
16754 {
16755 SCIP_CONS* upgdcons;
16756
16757 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16758 if( upgdcons != NULL )
16759 {
16760 /* add the upgraded constraint to the problem */
16761 SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16762 SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16763 (*nupgdconss)++;
16764
16765 /* mark the linear constraint being upgraded and to be removed after presolving;
16766 * don't delete it directly, because it may help to preprocess other linear constraints
16767 */
16768 assert(!consdata->upgraded);
16769 consdata->upgraded = TRUE;
16770
16771 /* delete upgraded inequalities immediately;
16772 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16773 */
16774 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16775 || !conshdlrdata->presolpairwise
16776 || (conshdlrdata->maxaggrnormscale == 0.0) )
16777 {
16778 SCIP_CALL( SCIPdelCons(scip, cons) );
16779 }
16780 }
16781 }
16782 }
16783 }
16784
16785 /* return the correct result code */
16786 if( cutoff )
16787 *result = SCIP_CUTOFF;
16788 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16789 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16790 *result = SCIP_SUCCESS;
16791 else
16792 *result = SCIP_DIDNOTFIND;
16793
16794 return SCIP_OKAY;
16795}
16796
16797
16798/** propagation conflict resolving method of constraint handler */
16799static
16800SCIP_DECL_CONSRESPROP(consRespropLinear)
16801{ /*lint --e{715}*/
16802 assert(scip != NULL);
16803 assert(cons != NULL);
16804 assert(result != NULL);
16805
16806 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16807
16808 return SCIP_OKAY;
16809}
16810
16811
16812/** variable rounding lock method of constraint handler */
16813static
16814SCIP_DECL_CONSLOCK(consLockLinear)
16815{ /*lint --e{715}*/
16816 SCIP_CONSDATA* consdata;
16817 SCIP_Bool haslhs;
16818 SCIP_Bool hasrhs;
16819 int i;
16820
16821 assert(scip != NULL);
16822 assert(cons != NULL);
16823 consdata = SCIPconsGetData(cons);
16824 assert(consdata != NULL);
16825
16826 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16827 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16828
16829 /* update rounding locks of every single variable */
16830 for( i = 0; i < consdata->nvars; ++i )
16831 {
16832 if( SCIPisPositive(scip, consdata->vals[i]) )
16833 {
16834 if( haslhs )
16835 {
16836 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16837 }
16838 if( hasrhs )
16839 {
16840 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16841 }
16842 }
16843 else
16844 {
16845 if( haslhs )
16846 {
16847 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16848 }
16849 if( hasrhs )
16850 {
16851 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16852 }
16853 }
16854 }
16855
16856 return SCIP_OKAY;
16857}
16858
16859
16860/** variable deletion method of constraint handler */
16861static
16862SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16863{
16864 assert(scip != NULL);
16865 assert(conshdlr != NULL);
16866 assert(conss != NULL || nconss == 0);
16867
16868 if( nconss > 0 )
16869 {
16870 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16871 }
16872
16873 return SCIP_OKAY;
16874}
16875
16876/** constraint display method of constraint handler */
16877static
16878SCIP_DECL_CONSPRINT(consPrintLinear)
16879{ /*lint --e{715}*/
16880 assert(scip != NULL);
16881 assert(conshdlr != NULL);
16882 assert(cons != NULL);
16883
16885
16886 return SCIP_OKAY;
16887}
16888
16889/** constraint copying method of constraint handler */
16890static
16891SCIP_DECL_CONSCOPY(consCopyLinear)
16892{ /*lint --e{715}*/
16893 SCIP_VAR** sourcevars;
16894 SCIP_Real* sourcecoefs;
16895 const char* consname;
16896 int nvars;
16897
16898 assert(scip != NULL);
16899 assert(sourcescip != NULL);
16900 assert(sourcecons != NULL);
16901
16902 /* get variables and coefficients of the source constraint */
16903 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16904 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16905 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16906
16907 if( name != NULL )
16908 consname = name;
16909 else
16910 consname = SCIPconsGetName(sourcecons);
16911
16912 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16913 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16914 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16915 assert(cons != NULL || *valid == FALSE);
16916
16917 /* @todo should also the checkabsolute flag of the constraint be copied? */
16918
16919 return SCIP_OKAY;
16920}
16921
16922/** find operators '<=', '==', '>=', [free] in input string and return those places
16923 *
16924 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16925 */
16926static
16928 const char* str, /**< null terminated input string */
16929 char** firstoperator, /**< pointer to store the string starting at the first operator */
16930 char** secondoperator, /**< pointer to store the string starting at the second operator */
16931 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16932 )
16933{
16934 char* curr;
16935
16936 assert(str != NULL);
16937 assert(firstoperator != NULL);
16938 assert(secondoperator != NULL);
16939
16940 *firstoperator = NULL;
16941 *secondoperator = NULL;
16942
16943 curr = (char*)str;
16944 *success = TRUE;
16945
16946 /* loop over the input string to find all operators */
16947 while( *curr && *success )
16948 {
16949 SCIP_Bool found = FALSE;
16950 int increment = 1;
16951
16952 /* try if we found a possible operator */
16953 switch( *curr )
16954 {
16955 case '<':
16956 case '=':
16957 case '>':
16958
16959 /* check if the two characters curr[0,1] form an operator together */
16960 if( curr[1] == '=' )
16961 {
16962 found = TRUE;
16963
16964 /* update increment to continue after this operator */
16965 increment = 2;
16966 }
16967 break;
16968 case '[':
16969 if( strncmp(curr, "[free]", 6) == 0 )
16970 {
16971 found = TRUE;
16972
16973 /* update increment to continue after this operator */
16974 increment = 6;
16975 }
16976 break;
16977 default:
16978 break;
16979 }
16980
16981 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16982 if( found )
16983 {
16984 if( *firstoperator == NULL )
16985 {
16986 *firstoperator = curr;
16987 }
16988 else
16989 {
16990 if( *secondoperator != NULL )
16991 {
16992 SCIPerrorMessage("Found more than two operators in line %s\n", str);
16993 *success = FALSE;
16994 }
16995 else if( strncmp(*firstoperator, "<=", 2) != 0 )
16996 {
16997 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16998 *success = FALSE;
16999 }
17000 else if( strncmp(curr, "<=", 2) != 0 )
17001 {
17002 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17003 *success = FALSE;
17004 }
17005
17006 *secondoperator = curr;
17007 }
17008 }
17009
17010 curr += increment;
17011 }
17012
17013 /* check if we did find at least one operator */
17014 if( *success )
17015 {
17016 if( *firstoperator == NULL )
17017 {
17018 SCIPerrorMessage("Could not find any operator in line %s\n", str);
17019 *success = FALSE;
17020 }
17021 }
17022}
17023
17024/** constraint parsing method of constraint handler */
17025static
17026SCIP_DECL_CONSPARSE(consParseLinear)
17027{ /*lint --e{715}*/
17028 SCIP_VAR** vars;
17029 SCIP_Real* coefs;
17030 int nvars;
17031 int coefssize;
17032 int requsize;
17033 SCIP_Real lhs;
17034 SCIP_Real rhs;
17035 char* endptr;
17036 char* firstop;
17037 char* secondop;
17038 SCIP_Bool operatorsuccess;
17039 char* lhsstrptr;
17040 char* rhsstrptr;
17041 char* varstrptr;
17042
17043 assert(scip != NULL);
17044 assert(success != NULL);
17045 assert(str != NULL);
17046 assert(name != NULL);
17047 assert(cons != NULL);
17048
17049 /* set left and right hand side to their default values */
17050 lhs = -SCIPinfinity(scip);
17051 rhs = SCIPinfinity(scip);
17052
17053 (*success) = FALSE;
17054
17055 /* return of string empty */
17056 if( !*str )
17057 return SCIP_OKAY;
17058
17059 /* ignore whitespace */
17060 SCIP_CALL( SCIPskipSpace((char**)&str) );
17061
17062 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17063 * and the special word [free]
17064 */
17065 findOperators(str, &firstop, &secondop, &operatorsuccess);
17066
17067 /* if the grammar is not valid for parsing a linear constraint, return */
17068 if( ! operatorsuccess )
17069 return SCIP_OKAY;
17070
17071 varstrptr = (char *)str;
17072 lhsstrptr = rhsstrptr = NULL;
17073 assert(firstop != NULL);
17074
17075 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17076 switch( *firstop )
17077 {
17078 case '<':
17079 assert(firstop[1] == '=');
17080 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17081 if( secondop != NULL )
17082 {
17083 assert(secondop[0] == '<' && secondop[1] == '=');
17084 lhsstrptr = (char *)str;
17085 varstrptr = firstop + 2;
17086 rhsstrptr = secondop + 2;
17087 }
17088 else
17089 {
17090 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17091 lhsstrptr = NULL;
17092 varstrptr = (char *)str;
17093 rhsstrptr = firstop + 2;
17094 }
17095 break;
17096 case '>':
17097 assert(firstop[1] == '=');
17098 assert(secondop == NULL);
17099 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17100 lhsstrptr = firstop + 2;
17101 break;
17102 case '=':
17103 assert(firstop[1] == '=');
17104 assert(secondop == NULL);
17105 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17106 rhsstrptr = firstop + 2;
17107 lhsstrptr = firstop + 2;
17108 break;
17109 case '[':
17110 assert(strncmp(firstop, "[free]", 6) == 0);
17111 assert(secondop == NULL);
17112 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17113 break;
17114 default:
17115 /* it should not be possible that a different character appears in that position */
17116 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17117 return SCIP_READERROR;
17118 }
17119
17120 /* parse left hand side, if necessary */
17121 if( lhsstrptr != NULL )
17122 {
17123 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17124 {
17125 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17126 return SCIP_OKAY;
17127 }
17128
17129 /* in case of an equation, assign the left also to the right hand side */
17130 if( rhsstrptr == lhsstrptr )
17131 rhs = lhs;
17132 }
17133
17134 /* parse right hand side, if different from left hand side */
17135 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17136 {
17137 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17138 {
17139 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17140 return SCIP_OKAY;
17141 }
17142 }
17143
17144 /* initialize buffers for storing the variables and coefficients */
17145 coefssize = 100;
17146 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17147 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17148
17149 assert(varstrptr != NULL);
17150
17151 /* parse linear sum to get variables and coefficients */
17152 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17153
17154 if( *success && requsize > coefssize )
17155 {
17156 /* realloc buffers and try again */
17157 coefssize = requsize;
17158 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17159 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17160
17161 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17162 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17163 }
17164
17165 if( !*success )
17166 {
17167 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17168 }
17169 else
17170 {
17171 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17172 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17173 }
17174
17175 SCIPfreeBufferArray(scip, &coefs);
17176 SCIPfreeBufferArray(scip, &vars);
17177
17178 return SCIP_OKAY;
17179}
17180
17181
17182/** constraint method of constraint handler which returns the variables (if possible) */
17183static
17184SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17185{ /*lint --e{715}*/
17186 SCIP_CONSDATA* consdata;
17187
17188 consdata = SCIPconsGetData(cons);
17189 assert(consdata != NULL);
17190
17191 if( varssize < consdata->nvars )
17192 (*success) = FALSE;
17193 else
17194 {
17195 assert(vars != NULL);
17196
17197 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17198 (*success) = TRUE;
17199 }
17200
17201 return SCIP_OKAY;
17202}
17203
17204/**! [Callback for the number of variables]*/
17205/** constraint method of constraint handler which returns the number of variables (if possible) */
17206static
17207SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17208{ /*lint --e{715}*/
17209 SCIP_CONSDATA* consdata;
17210
17211 consdata = SCIPconsGetData(cons);
17212 assert(consdata != NULL);
17213
17214 (*nvars) = consdata->nvars;
17215 (*success) = TRUE;
17216
17217 return SCIP_OKAY;
17218}
17219/**! [Callback for the number of variables]*/
17220
17221/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17222static
17223SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17224{ /*lint --e{715}*/
17225 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17226
17227 return SCIP_OKAY;
17228}
17229
17230/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17231static
17232SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17233{ /*lint --e{715}*/
17234 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17235
17236 return SCIP_OKAY;
17237}
17238
17239/*
17240 * Callback methods of event handler
17241 */
17242
17243/** execution method of event handler */
17244static
17245SCIP_DECL_EVENTEXEC(eventExecLinear)
17246{ /*lint --e{715}*/
17247 SCIP_CONS* cons;
17248 SCIP_CONSDATA* consdata;
17249 SCIP_VAR* var;
17250 SCIP_EVENTTYPE eventtype;
17251
17252 assert(scip != NULL);
17253 assert(eventhdlr != NULL);
17254 assert(eventdata != NULL);
17255 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17256 assert(event != NULL);
17257
17258 cons = eventdata->cons;
17259 assert(cons != NULL);
17260 consdata = SCIPconsGetData(cons);
17261 assert(consdata != NULL);
17262
17263 /* we can skip events droped for deleted constraints */
17264 if( SCIPconsIsDeleted(cons) )
17265 return SCIP_OKAY;
17266
17267 eventtype = SCIPeventGetType(event);
17268 var = SCIPeventGetVar(event);
17269
17270 if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17271 {
17272 SCIP_Real oldbound;
17273 SCIP_Real newbound;
17274 SCIP_Real val;
17275 int varpos;
17276
17277 varpos = eventdata->varpos;
17278 assert(0 <= varpos && varpos < consdata->nvars);
17279 oldbound = SCIPeventGetOldbound(event);
17280 newbound = SCIPeventGetNewbound(event);
17281 assert(var != NULL);
17282 assert(consdata->vars[varpos] == var);
17283 val = consdata->vals[varpos];
17284
17285 /* we only need to update the activities if the constraint is active,
17286 * otherwise we mark them to be invalid
17287 */
17288 if( SCIPconsIsActive(cons) )
17289 {
17290 /* update the activity values */
17291 if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17292 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17293 else
17294 {
17295 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17296 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17297 }
17298 }
17299 else
17301
17302 consdata->presolved = FALSE;
17303 consdata->rangedrowpropagated = 0;
17304
17305 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17306 if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17307 {
17309
17310 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17311 if( consdata->maxactdeltavar == var )
17312 {
17313 consdata->maxactdelta = SCIP_INVALID;
17314 consdata->maxactdeltavar = NULL;
17315 }
17316
17317 /* check whether bound tightening might now be successful */
17318 if( consdata->boundstightened > 0)
17319 {
17320 switch( eventtype )
17321 {
17323 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17324 consdata->boundstightened = 0;
17325 break;
17327 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17328 consdata->boundstightened = 0;
17329 break;
17330 default:
17331 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17332 return SCIP_INVALIDDATA;
17333 }
17334 }
17335 }
17336 /* update maximal activity delta if a bound was relaxed */
17337 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17338 {
17339 SCIP_Real lb;
17340 SCIP_Real ub;
17341 SCIP_Real domain;
17342 SCIP_Real delta;
17343
17344 assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17345
17346 lb = SCIPvarGetLbLocal(var);
17347 ub = SCIPvarGetUbLocal(var);
17348
17349 domain = ub - lb;
17350 delta = REALABS(val) * domain;
17351
17352 if( delta > consdata->maxactdelta )
17353 {
17354 consdata->maxactdelta = delta;
17355 consdata->maxactdeltavar = var;
17356 }
17357 }
17358 }
17359 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17360 {
17361 /* we want to remove the fixed variable */
17362 consdata->presolved = FALSE;
17363 consdata->removedfixings = FALSE;
17364 consdata->rangedrowpropagated = 0;
17365
17366 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17367 if( consdata->maxactdeltavar == var )
17368 {
17369 consdata->maxactdelta = SCIP_INVALID;
17370 consdata->maxactdeltavar = NULL;
17371 }
17372 }
17373 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17374 {
17375 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17378 consdata->presolved = FALSE;
17379 }
17380 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17381 {
17382 SCIP_Real oldbound;
17383 SCIP_Real newbound;
17384 SCIP_Real val;
17385 int varpos;
17386
17387 varpos = eventdata->varpos;
17388 assert(0 <= varpos && varpos < consdata->nvars);
17389 oldbound = SCIPeventGetOldbound(event);
17390 newbound = SCIPeventGetNewbound(event);
17391 assert(var != NULL);
17392 assert(consdata->vars[varpos] == var);
17393 val = consdata->vals[varpos];
17394
17395 consdata->rangedrowpropagated = 0;
17396
17397 /* update the activity values */
17398 if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17399 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17400 else
17401 {
17402 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17403 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17404 }
17405
17406 /* if the variable is binary but not fixed it had to become binary due to this global change */
17408 {
17410 consdata->indexsorted = FALSE;
17411 else
17412 consdata->coefsorted = FALSE;
17413 }
17414 }
17415 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17416 {
17418
17419 /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17420 consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17421
17422 /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17423 consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17424 }
17425 else
17426 {
17427 assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17428 consdata->varsdeleted = TRUE;
17429 }
17430
17431 return SCIP_OKAY;
17432}
17433
17434
17435/*
17436 * Callback methods of conflict handler
17437 */
17438
17439/** conflict processing method of conflict handler (called when conflict was found) */
17440static
17441SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17442{ /*lint --e{715}*/
17443 SCIP_VAR** vars;
17444 SCIP_Real* vals;
17445 SCIP_Real lhs;
17446 int i;
17447
17448 assert(scip != NULL);
17449 assert(conflicthdlr != NULL);
17450 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17451 assert(bdchginfos != NULL || nbdchginfos == 0);
17452 assert(result != NULL);
17453
17454 /* don't process already resolved conflicts */
17455 if( resolved )
17456 {
17457 *result = SCIP_DIDNOTRUN;
17458 return SCIP_OKAY;
17459 }
17460
17461 *result = SCIP_DIDNOTFIND;
17462
17463 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17464 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17465 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17466 lhs = 1.0;
17467 for( i = 0; i < nbdchginfos; ++i )
17468 {
17469 assert(bdchginfos != NULL);
17470
17471 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17472
17473 /* we can only treat binary variables */
17474 /**@todo extend linear conflict constraints to some non-binary cases */
17475 if( !SCIPvarIsBinary(vars[i]) )
17476 break;
17477
17478 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17479 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17480 vals[i] = 1.0;
17481 else
17482 {
17483 vals[i] = -1.0;
17484 lhs -= 1.0;
17485 }
17486 }
17487
17488 if( i == nbdchginfos )
17489 {
17490 SCIP_CONS* cons;
17491 SCIP_CONS* upgdcons;
17492 char consname[SCIP_MAXSTRLEN];
17493
17494 /* create a constraint out of the conflict set */
17496 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17497 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17498
17499 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17500 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17501 if( upgdcons != NULL )
17502 {
17503 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17504 cons = upgdcons;
17505 }
17506
17507 /* add conflict to SCIP */
17508 SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17509
17510 *result = SCIP_CONSADDED;
17511 }
17512
17513 /* free temporary memory */
17514 SCIPfreeBufferArray(scip, &vals);
17515 SCIPfreeBufferArray(scip, &vars);
17516
17517 return SCIP_OKAY;
17518}
17519
17520
17521/*
17522 * Nonlinear constraint upgrading
17523 */
17524
17525/** tries to upgrade a nonlinear constraint into a linear constraint */
17526static
17527SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17528{
17529 SCIP_CONSDATA* consdata;
17530 SCIP_EXPR* expr;
17531 SCIP_Real lhs;
17532 SCIP_Real rhs;
17533 int i;
17534
17535 assert(nupgdconss != NULL);
17536 assert(upgdconss != NULL);
17537 assert(upgdconsssize > 0);
17538
17539 expr = SCIPgetExprNonlinear(cons);
17540 assert(expr != NULL);
17541
17542 /* not a linear constraint if the expression is not a sum
17543 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17544 */
17545 if( !SCIPisExprSum(scip, expr) )
17546 return SCIP_OKAY;
17547
17548 /* if at least one child is not a variable, then not a linear constraint */
17549 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17550 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17551 return SCIP_OKAY;
17552
17553 /* consider constant part of the sum expression */
17556
17557 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17558 0, NULL, NULL, lhs, rhs,
17562 SCIPconsIsStickingAtNode(cons)) );
17563 assert(upgdconss[0] != NULL);
17564
17565 consdata = SCIPconsGetData(upgdconss[0]);
17566
17567 /* add linear terms */
17569 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17570 {
17572 }
17573
17574 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17575 consdata->checkabsolute = TRUE;
17576
17577 *nupgdconss = 1;
17578
17579 SCIPdebugMsg(scip, "created linear constraint:\n");
17580 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17581
17582 return SCIP_OKAY;
17583} /*lint !e715*/
17584
17585/*
17586 * constraint specific interface methods
17587 */
17588
17589/** creates the handler for linear constraints and includes it in SCIP */
17591 SCIP* scip /**< SCIP data structure */
17592 )
17593{
17594 SCIP_CONSHDLRDATA* conshdlrdata;
17595 SCIP_CONSHDLR* conshdlr;
17596 SCIP_EVENTHDLR* eventhdlr;
17597 SCIP_CONFLICTHDLR* conflicthdlr;
17598
17599 assert(scip != NULL);
17600
17601 /* create event handler for bound change events */
17603 eventExecLinear, NULL) );
17604
17605 /* create conflict handler for linear constraints */
17607 conflictExecLinear, NULL) );
17608
17609 /* create constraint handler data */
17610 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17611
17612 /* include constraint handler */
17615 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17616 conshdlrdata) );
17617
17618 assert(conshdlr != NULL);
17619
17620 /* set non-fundamental callbacks via specific setter functions */
17621 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17622 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17623 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17624 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17625 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17626 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17627 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17628 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17629 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17630 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17631 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17632 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17633 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17634 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17635 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17637 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17640 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17641 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17643 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17644 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17645 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17646 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17647
17648 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17649 {
17650 /* include the linear constraint upgrade in the nonlinear constraint handler */
17652 }
17653
17654 /* add linear constraint handler parameters */
17656 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17657 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17658 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17660 "constraints/" CONSHDLR_NAME "/maxrounds",
17661 "maximal number of separation rounds per node (-1: unlimited)",
17662 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17664 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17665 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17666 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17668 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17669 "maximal number of cuts separated per separation round",
17670 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17672 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17673 "maximal number of cuts separated per separation round in the root node",
17674 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17676 "constraints/" CONSHDLR_NAME "/presolpairwise",
17677 "should pairwise constraint comparison be performed in presolving?",
17678 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17680 "constraints/" CONSHDLR_NAME "/presolusehashing",
17681 "should hash table be used for detecting redundant constraints in advance",
17682 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17684 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17685 "number for minimal pairwise presolve comparisons",
17686 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17688 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17689 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17690 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17692 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17693 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17694 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17696 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17697 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17698 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17700 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17701 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17702 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17704 "constraints/" CONSHDLR_NAME "/separateall",
17705 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17706 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17708 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17709 "should presolving search for aggregations in equations",
17710 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17712 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17713 "should presolving try to simplify inequalities",
17714 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17716 "constraints/" CONSHDLR_NAME "/dualpresolving",
17717 "should dual presolving steps be performed?",
17718 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17720 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17721 "should stuffing of singleton continuous variables be performed?",
17722 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17724 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17725 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17726 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17728 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17729 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17731 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17732 "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)?",
17733 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17735 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17736 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17737 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17739 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17740 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17741 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17743 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17744 "should presolving try to detect subsets of constraints parallel to the objective function?",
17745 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17747 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17748 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17749 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17751 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17752 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17753 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17755 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17756 "maximum depth to apply ranged row propagation",
17757 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17759 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17760 "frequency for applying ranged row propagation",
17761 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17763 "constraints/" CONSHDLR_NAME "/multaggrremove",
17764 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17765 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17767 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17768 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17769 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17771 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17772 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17773 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17775 "constraints/" CONSHDLR_NAME "/extractcliques",
17776 "should Cliques be extracted?",
17777 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17778
17779 return SCIP_OKAY;
17780}
17781
17782/** includes a linear constraint update method into the linear constraint handler */
17784 SCIP* scip, /**< SCIP data structure */
17785 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17786 int priority, /**< priority of upgrading method */
17787 const char* conshdlrname /**< name of the constraint handler */
17788 )
17789{
17790 SCIP_CONSHDLR* conshdlr;
17791 SCIP_CONSHDLRDATA* conshdlrdata;
17792 SCIP_LINCONSUPGRADE* linconsupgrade;
17794 char paramdesc[SCIP_MAXSTRLEN];
17795
17796 assert(scip != NULL);
17797 assert(linconsupgd != NULL);
17798 assert(conshdlrname != NULL );
17799
17800 /* find the linear constraint handler */
17801 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17802 if( conshdlr == NULL )
17803 {
17804 SCIPerrorMessage("linear constraint handler not found\n");
17805 return SCIP_PLUGINNOTFOUND;
17806 }
17807
17808 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17809 assert(conshdlrdata != NULL);
17810
17811 /* check if linear constraint update method already exists in constraint handler data */
17812 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17813 {
17814 /* create a linear constraint upgrade data object */
17815 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17816
17817 /* insert linear constraint update method into constraint handler data */
17818 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17819
17820 /* adds parameter to turn on and off the upgrading step */
17821 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17822 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17824 paramname, paramdesc,
17825 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17826 }
17827
17828 return SCIP_OKAY;
17829}
17830
17831/** creates and captures a linear constraint
17832 *
17833 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17834 */
17836 SCIP* scip, /**< SCIP data structure */
17837 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17838 const char* name, /**< name of constraint */
17839 int nvars, /**< number of nonzeros in the constraint */
17840 SCIP_VAR** vars, /**< array with variables of constraint entries */
17841 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17842 SCIP_Real lhs, /**< left hand side of constraint */
17843 SCIP_Real rhs, /**< right hand side of constraint */
17844 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17845 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17846 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17847 * Usually set to TRUE. */
17848 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17849 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17850 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17851 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17852 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17853 * Usually set to TRUE. */
17854 SCIP_Bool local, /**< is constraint only valid locally?
17855 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17856 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17857 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17858 * adds coefficients to this constraint. */
17859 SCIP_Bool dynamic, /**< is constraint subject to aging?
17860 * Usually set to FALSE. Set to TRUE for own cuts which
17861 * are separated as constraints. */
17862 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17863 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17864 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17865 * if it may be moved to a more global node?
17866 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17867 )
17868{
17869 SCIP_CONSHDLR* conshdlr;
17870 SCIP_CONSDATA* consdata;
17871 int j;
17872
17873 assert(scip != NULL);
17874 assert(cons != NULL);
17875
17876 /* find the linear constraint handler */
17877 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17878 if( conshdlr == NULL )
17879 {
17880 SCIPerrorMessage("linear constraint handler not found\n");
17881 return SCIP_PLUGINNOTFOUND;
17882 }
17883
17884 for( j = 0; j < nvars; ++j )
17885 {
17886 if( SCIPisInfinity(scip, REALABS(vals[j])) )
17887 {
17888 SCIPerrorMessage("coefficient of variable <%s> is infinite.\n", SCIPvarGetName(vars[j]));
17889 SCIPABORT();
17890 return SCIP_INVALIDDATA;
17891 }
17892 }
17893
17894 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17895 * constraint after presolving we have to ensure that it holds active variables
17896 */
17897 if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17898 {
17899 SCIP_VAR** consvars;
17900 SCIP_Real* consvals;
17901 SCIP_Real constant = 0.0;
17902 int nconsvars;
17903 int requiredsize;
17904
17905 nconsvars = nvars;
17906 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17907 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17908
17909 /* get active variables for new constraint */
17910 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17911
17912 /* if space was not enough we need to resize the buffers */
17913 if( requiredsize > nconsvars )
17914 {
17915 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17916 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17917
17918 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17919 assert(requiredsize <= nconsvars);
17920 }
17921
17922 /* adjust sides and check that we do not subtract infinity values */
17923 if( SCIPisInfinity(scip, REALABS(constant)) )
17924 {
17925 if( constant < 0.0 )
17926 {
17927 if( SCIPisInfinity(scip, lhs) )
17928 {
17929 SCIPfreeBufferArray(scip, &consvals);
17930 SCIPfreeBufferArray(scip, &consvars);
17931
17932 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);
17933
17934 SCIPABORT();
17935 return SCIP_INVALIDDATA; /*lint !e527*/
17936 }
17937 if( SCIPisInfinity(scip, rhs) )
17938 {
17939 SCIPfreeBufferArray(scip, &consvals);
17940 SCIPfreeBufferArray(scip, &consvars);
17941
17942 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);
17943
17944 SCIPABORT();
17945 return SCIP_INVALIDDATA; /*lint !e527*/
17946 }
17947
17948 lhs = -SCIPinfinity(scip);
17949 rhs = -SCIPinfinity(scip);
17950 }
17951 else
17952 {
17953 if( SCIPisInfinity(scip, -lhs) )
17954 {
17955 SCIPfreeBufferArray(scip, &consvals);
17956 SCIPfreeBufferArray(scip, &consvars);
17957
17958 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);
17959
17960 SCIPABORT();
17961 return SCIP_INVALIDDATA; /*lint !e527*/
17962 }
17963 if( SCIPisInfinity(scip, -rhs) )
17964 {
17965 SCIPfreeBufferArray(scip, &consvals);
17966 SCIPfreeBufferArray(scip, &consvars);
17967
17968 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);
17969
17970 SCIPABORT();
17971 return SCIP_INVALIDDATA; /*lint !e527*/
17972 }
17973
17974 lhs = SCIPinfinity(scip);
17975 rhs = SCIPinfinity(scip);
17976 }
17977 }
17978 else
17979 {
17980 if( !SCIPisInfinity(scip, REALABS(lhs)) )
17981 lhs -= constant;
17982 if( !SCIPisInfinity(scip, REALABS(rhs)) )
17983 rhs -= constant;
17984
17985 if( SCIPisInfinity(scip, -lhs) )
17986 lhs = -SCIPinfinity(scip);
17987 else if( SCIPisInfinity(scip, lhs) )
17988 lhs = SCIPinfinity(scip);
17989
17990 if( SCIPisInfinity(scip, rhs) )
17991 rhs = SCIPinfinity(scip);
17992 else if( SCIPisInfinity(scip, -rhs) )
17993 rhs = -SCIPinfinity(scip);
17994 }
17995
17996 /* create constraint data */
17997 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17998 assert(consdata != NULL);
17999
18000 SCIPfreeBufferArray(scip, &consvals);
18001 SCIPfreeBufferArray(scip, &consvars);
18002 }
18003 else
18004 {
18005 /* create constraint data */
18006 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18007 assert(consdata != NULL);
18008 }
18009
18010#ifndef NDEBUG
18011 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18012 if( check || enforce )
18013 {
18014 int n;
18015 for(n = consdata->nvars - 1; n >= 0; --n )
18016 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18017 }
18018#endif
18019
18020 /* create constraint */
18021 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18022 local, modifiable, dynamic, removable, stickingatnode) );
18023
18024 return SCIP_OKAY;
18025}
18026
18027/** creates and captures a linear constraint
18028 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18029 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18030 *
18031 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18032 *
18033 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18034 */
18036 SCIP* scip, /**< SCIP data structure */
18037 SCIP_CONS** cons, /**< pointer to hold the created constraint */
18038 const char* name, /**< name of constraint */
18039 int nvars, /**< number of nonzeros in the constraint */
18040 SCIP_VAR** vars, /**< array with variables of constraint entries */
18041 SCIP_Real* vals, /**< array with coefficients of constraint entries */
18042 SCIP_Real lhs, /**< left hand side of constraint */
18043 SCIP_Real rhs /**< right hand side of constraint */
18044 )
18045{
18046 assert(scip != NULL);
18047
18048 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18050
18051 return SCIP_OKAY;
18052}
18053
18054/** creates by copying and captures a linear constraint */
18056 SCIP* scip, /**< target SCIP data structure */
18057 SCIP_CONS** cons, /**< pointer to store the created target constraint */
18058 SCIP* sourcescip, /**< source SCIP data structure */
18059 const char* name, /**< name of constraint */
18060 int nvars, /**< number of variables in source variable array */
18061 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18062 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18063 SCIP_Real lhs, /**< left hand side of the linear constraint */
18064 SCIP_Real rhs, /**< right hand side of the linear constraint */
18065 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18066 * variables of the target SCIP */
18067 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18068 * target constraints */
18069 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18070 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18071 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18072 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18073 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18074 SCIP_Bool local, /**< is constraint only valid locally? */
18075 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18076 SCIP_Bool dynamic, /**< is constraint subject to aging? */
18077 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18078 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18079 * if it may be moved to a more global node? */
18080 SCIP_Bool global, /**< create a global or a local copy? */
18081 SCIP_Bool* valid /**< pointer to store if the copying was valid */
18082 )
18083{
18084 SCIP_VAR** vars;
18085 SCIP_Real* coefs;
18086
18087 SCIP_Real constant;
18088 int requiredsize;
18089 int v;
18090 SCIP_Bool success;
18091
18092 if( SCIPisGT(scip, lhs, rhs) )
18093 {
18094 *valid = FALSE;
18095 return SCIP_OKAY;
18096 }
18097
18098 (*valid) = TRUE;
18099
18100 if( nvars == 0 )
18101 {
18102 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18103 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18104 return SCIP_OKAY;
18105 }
18106
18107 /* duplicate variable array */
18108 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
18109
18110 /* duplicate coefficient array */
18111 if( sourcecoefs != NULL )
18112 {
18113 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18114 }
18115 else
18116 {
18117 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18118 for( v = 0; v < nvars; ++v )
18119 coefs[v] = 1.0;
18120 }
18121
18122 constant = 0.0;
18123
18124 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18125 * the target SCIP
18126 */
18127 if( !SCIPvarIsOriginal(vars[0]) )
18128 {
18129 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18130
18131 if( requiredsize > nvars )
18132 {
18133 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18134 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18135
18136 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18137 assert(requiredsize <= nvars);
18138 }
18139 }
18140 else
18141 {
18142 for( v = 0; v < nvars; ++v )
18143 {
18144 assert(SCIPvarIsOriginal(vars[v]));
18145 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18146 assert(vars[v] != NULL);
18147 }
18148 }
18149
18150 success = TRUE;
18151 /* map variables of the source constraint to variables of the target SCIP */
18152 for( v = 0; v < nvars && success; ++v )
18153 {
18154 SCIP_VAR* var;
18155 var = vars[v];
18156
18157 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18158 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18159
18160 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18161 assert(!(success) || vars[v] != NULL);
18162 }
18163
18164 /* only create the target constraint, if all variables could be copied */
18165 if( success )
18166 {
18167 if( !SCIPisInfinity(scip, -lhs) )
18168 lhs -= constant;
18169
18170 if( !SCIPisInfinity(scip, rhs) )
18171 rhs -= constant;
18172
18173 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18174 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18175 }
18176 else
18177 *valid = FALSE;
18178
18179 /* free buffer array */
18180 SCIPfreeBufferArray(scip, &coefs);
18181 SCIPfreeBufferArray(scip, &vars);
18182
18183 return SCIP_OKAY;
18184}
18185
18186/** adds coefficient to linear constraint (if it is not zero) */
18188 SCIP* scip, /**< SCIP data structure */
18189 SCIP_CONS* cons, /**< constraint data */
18190 SCIP_VAR* var, /**< variable of constraint entry */
18191 SCIP_Real val /**< coefficient of constraint entry */
18192 )
18193{
18194 assert(scip != NULL);
18195 assert(cons != NULL);
18196 assert(var != NULL);
18197
18198 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18199 {
18200 SCIPerrorMessage("constraint is not linear\n");
18201 return SCIP_INVALIDDATA;
18202 }
18203
18204 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18205 * constraint after presolving we have to ensure that it holds active variables
18206 */
18208 {
18209 SCIP_CONSDATA* consdata;
18210 SCIP_VAR** consvars;
18211 SCIP_Real* consvals;
18212 SCIP_Real constant = 0.0;
18213 SCIP_Real rhs;
18214 SCIP_Real lhs;
18215 int nconsvars;
18216 int requiredsize;
18217 int v;
18218
18219 nconsvars = 1;
18220 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18221 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18222 consvars[0] = var;
18223 consvals[0] = val;
18224
18225 /* get active variables for new constraint */
18226 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18227
18228 /* if space was not enough we need to resize the buffers */
18229 if( requiredsize > nconsvars )
18230 {
18231 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18232 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18233
18234 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18235 assert(requiredsize <= nconsvars);
18236 }
18237
18238 consdata = SCIPconsGetData(cons);
18239 assert(consdata != NULL);
18240
18241 lhs = consdata->lhs;
18242 rhs = consdata->rhs;
18243
18244 /* adjust sides and check that we do not subtract infinity values */
18245 /* constant is infinite */
18246 if( SCIPisInfinity(scip, REALABS(constant)) )
18247 {
18248 if( constant < 0.0 )
18249 {
18250 if( SCIPisInfinity(scip, lhs) )
18251 {
18252 SCIPfreeBufferArray(scip, &consvals);
18253 SCIPfreeBufferArray(scip, &consvars);
18254
18255 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));
18256
18257 SCIPABORT();
18258 return SCIP_INVALIDDATA; /*lint !e527*/
18259 }
18260 if( SCIPisInfinity(scip, rhs) )
18261 {
18262 SCIPfreeBufferArray(scip, &consvals);
18263 SCIPfreeBufferArray(scip, &consvars);
18264
18265 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));
18266
18267 SCIPABORT();
18268 return SCIP_INVALIDDATA; /*lint !e527*/
18269 }
18270
18271 lhs = -SCIPinfinity(scip);
18272 rhs = -SCIPinfinity(scip);
18273 }
18274 else
18275 {
18276 if( SCIPisInfinity(scip, -lhs) )
18277 {
18278 SCIPfreeBufferArray(scip, &consvals);
18279 SCIPfreeBufferArray(scip, &consvars);
18280
18281 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));
18282
18283 SCIPABORT();
18284 return SCIP_INVALIDDATA; /*lint !e527*/
18285 }
18286 if( SCIPisInfinity(scip, -rhs) )
18287 {
18288 SCIPfreeBufferArray(scip, &consvals);
18289 SCIPfreeBufferArray(scip, &consvars);
18290
18291 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));
18292
18293 SCIPABORT();
18294 return SCIP_INVALIDDATA; /*lint !e527*/
18295 }
18296
18297 lhs = SCIPinfinity(scip);
18298 rhs = SCIPinfinity(scip);
18299 }
18300 }
18301 /* constant is not infinite */
18302 else
18303 {
18304 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18305 lhs -= constant;
18306 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18307 rhs -= constant;
18308
18309 if( SCIPisInfinity(scip, -lhs) )
18310 lhs = -SCIPinfinity(scip);
18311 else if( SCIPisInfinity(scip, lhs) )
18312 lhs = SCIPinfinity(scip);
18313
18314 if( SCIPisInfinity(scip, rhs) )
18315 rhs = SCIPinfinity(scip);
18316 else if( SCIPisInfinity(scip, -rhs) )
18317 rhs = -SCIPinfinity(scip);
18318 }
18319
18320 /* add all active variables to constraint */
18321 for( v = nconsvars - 1; v >= 0; --v )
18322 {
18323 if( !SCIPisZero(scip, consvals[v]) )
18324 {
18325 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18326 }
18327 }
18328
18329 /* update left and right hand sides */
18330 SCIP_CALL( chgLhs(scip, cons, lhs));
18331 SCIP_CALL( chgRhs(scip, cons, rhs));
18332
18333 SCIPfreeBufferArray(scip, &consvals);
18334 SCIPfreeBufferArray(scip, &consvars);
18335 }
18336 else if( !SCIPisZero(scip, val) )
18337 {
18338 SCIP_CALL( addCoef(scip, cons, var, val) );
18339 }
18340
18341 return SCIP_OKAY;
18342}
18343
18344/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18345 * not yet contained in the constraint
18346 *
18347 * @note This method may only be called during problem creation stage for an original constraint and variable.
18348 *
18349 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18350 */
18352 SCIP* scip, /**< SCIP data structure */
18353 SCIP_CONS* cons, /**< constraint data */
18354 SCIP_VAR* var, /**< variable of constraint entry */
18355 SCIP_Real val /**< new coefficient of constraint entry */
18356 )
18357{
18358 SCIP_CONSDATA* consdata;
18359 SCIP_VAR** vars;
18360 SCIP_Bool found;
18361 int i;
18362
18363 assert(scip != NULL);
18364 assert(cons != NULL);
18365 assert(var != NULL);
18366
18367 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18368 {
18369 SCIPerrorMessage("constraint is not linear\n");
18370 return SCIP_INVALIDDATA;
18371 }
18372
18374 {
18375 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18376 return SCIP_INVALIDDATA;
18377 }
18378
18379 consdata = SCIPconsGetData(cons);
18380 assert(consdata != NULL);
18381
18382 vars = consdata->vars;
18383 found = FALSE;
18384 i = 0;
18385 while( i < consdata->nvars )
18386 {
18387 if( vars[i] == var )
18388 {
18389 if( found || SCIPisZero(scip, val) )
18390 {
18391 SCIP_CALL( delCoefPos(scip, cons, i) );
18392
18393 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18394 i--;
18395 }
18396 else
18397 {
18398 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18399 }
18400 found = TRUE;
18401 }
18402 i++;
18403 }
18404
18405 if( !found )
18406 {
18407 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18408 }
18409
18410 return SCIP_OKAY;
18411}
18412
18413/** deletes variable from linear constraint
18414 *
18415 * @note This method may only be called during problem creation stage for an original constraint and variable.
18416 *
18417 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18418 */
18420 SCIP* scip, /**< SCIP data structure */
18421 SCIP_CONS* cons, /**< constraint data */
18422 SCIP_VAR* var /**< variable of constraint entry */
18423 )
18424{
18425 assert(scip != NULL);
18426 assert(cons != NULL);
18427 assert(var != NULL);
18428
18429 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18430
18431 return SCIP_OKAY;
18432}
18433
18434/** gets left hand side of linear constraint */
18436 SCIP* scip, /**< SCIP data structure */
18437 SCIP_CONS* cons /**< constraint data */
18438 )
18439{
18440 SCIP_CONSDATA* consdata;
18441
18442 assert(scip != NULL);
18443 assert(cons != NULL);
18444
18445 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18446 {
18447 SCIPerrorMessage("constraint is not linear\n");
18448 SCIPABORT();
18449 return SCIP_INVALID; /*lint !e527*/
18450 }
18451
18452 consdata = SCIPconsGetData(cons);
18453 assert(consdata != NULL);
18454
18455 return consdata->lhs;
18456}
18457
18458/** gets right hand side of linear constraint */
18460 SCIP* scip, /**< SCIP data structure */
18461 SCIP_CONS* cons /**< constraint data */
18462 )
18463{
18464 SCIP_CONSDATA* consdata;
18465
18466 assert(scip != NULL);
18467 assert(cons != NULL);
18468
18469 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18470 {
18471 SCIPerrorMessage("constraint is not linear\n");
18472 SCIPABORT();
18473 return SCIP_INVALID; /*lint !e527*/
18474 }
18475
18476 consdata = SCIPconsGetData(cons);
18477 assert(consdata != NULL);
18478
18479 return consdata->rhs;
18480}
18481
18482/** changes left hand side of linear constraint */
18484 SCIP* scip, /**< SCIP data structure */
18485 SCIP_CONS* cons, /**< constraint data */
18486 SCIP_Real lhs /**< new left hand side */
18487 )
18488{
18489 assert(scip != NULL);
18490 assert(cons != NULL);
18491
18492 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18493 {
18494 SCIPerrorMessage("constraint is not linear\n");
18495 return SCIP_INVALIDDATA;
18496 }
18497
18498 SCIP_CALL( chgLhs(scip, cons, lhs) );
18499
18500 return SCIP_OKAY;
18501}
18502
18503/** changes right hand side of linear constraint */
18505 SCIP* scip, /**< SCIP data structure */
18506 SCIP_CONS* cons, /**< constraint data */
18507 SCIP_Real rhs /**< new right hand side */
18508 )
18509{
18510 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18511 {
18512 SCIPerrorMessage("constraint is not linear\n");
18513 return SCIP_INVALIDDATA;
18514 }
18515
18516 SCIP_CALL( chgRhs(scip, cons, rhs) );
18517
18518 return SCIP_OKAY;
18519}
18520
18521/** gets the number of variables in the linear constraint */
18523 SCIP* scip, /**< SCIP data structure */
18524 SCIP_CONS* cons /**< constraint data */
18525 )
18526{
18527 SCIP_CONSDATA* consdata;
18528
18529 assert(scip != NULL);
18530 assert(cons != NULL);
18531
18532 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18533 {
18534 SCIPerrorMessage("constraint is not linear\n");
18535 SCIPABORT();
18536 return -1; /*lint !e527*/
18537 }
18538
18539 consdata = SCIPconsGetData(cons);
18540 assert(consdata != NULL);
18541
18542 return consdata->nvars;
18543}
18544
18545/** gets the array of variables in the linear constraint; the user must not modify this array! */
18547 SCIP* scip, /**< SCIP data structure */
18548 SCIP_CONS* cons /**< constraint data */
18549 )
18550{
18551 SCIP_CONSDATA* consdata;
18552
18553 assert(scip != NULL);
18554 assert(cons != NULL);
18555
18556 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18557 {
18558 SCIPerrorMessage("constraint is not linear\n");
18559 SCIPABORT();
18560 return NULL; /*lint !e527*/
18561 }
18562
18563 consdata = SCIPconsGetData(cons);
18564 assert(consdata != NULL);
18565
18566 return consdata->vars;
18567}
18568
18569/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18571 SCIP* scip, /**< SCIP data structure */
18572 SCIP_CONS* cons /**< constraint data */
18573 )
18574{
18575 SCIP_CONSDATA* consdata;
18576
18577 assert(scip != NULL);
18578 assert(cons != NULL);
18579
18580 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18581 {
18582 SCIPerrorMessage("constraint is not linear\n");
18583 SCIPABORT();
18584 return NULL; /*lint !e527*/
18585 }
18586
18587 consdata = SCIPconsGetData(cons);
18588 assert(consdata != NULL);
18589
18590 return consdata->vals;
18591}
18592
18593/** gets the activity of the linear constraint in the given solution
18594 *
18595 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18596 * comprises positive and negative infinity contributions
18597 */
18599 SCIP* scip, /**< SCIP data structure */
18600 SCIP_CONS* cons, /**< constraint data */
18601 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18602 )
18603{
18604 SCIP_CONSDATA* consdata;
18605
18606 assert(scip != NULL);
18607 assert(cons != NULL);
18608
18609 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18610 {
18611 SCIPerrorMessage("constraint is not linear\n");
18612 SCIPABORT();
18613 return SCIP_INVALID; /*lint !e527*/
18614 }
18615
18616 consdata = SCIPconsGetData(cons);
18617 assert(consdata != NULL);
18618
18619 if( consdata->row != NULL )
18620 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18621 else
18622 return consdataGetActivity(scip, consdata, sol);
18623}
18624
18625/** gets the feasibility of the linear constraint in the given solution */
18627 SCIP* scip, /**< SCIP data structure */
18628 SCIP_CONS* cons, /**< constraint data */
18629 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18630 )
18631{
18632 SCIP_CONSDATA* consdata;
18633
18634 assert(scip != NULL);
18635 assert(cons != NULL);
18636
18637 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18638 {
18639 SCIPerrorMessage("constraint is not linear\n");
18640 SCIPABORT();
18641 return SCIP_INVALID; /*lint !e527*/
18642 }
18643
18644 consdata = SCIPconsGetData(cons);
18645 assert(consdata != NULL);
18646
18647 if( consdata->row != NULL )
18648 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18649 else
18650 return consdataGetFeasibility(scip, consdata, sol);
18651}
18652
18653/** gets the dual solution of the linear constraint in the current LP */
18655 SCIP* scip, /**< SCIP data structure */
18656 SCIP_CONS* cons /**< constraint data */
18657 )
18658{
18659 SCIP_CONSDATA* consdata;
18660
18661 assert(scip != NULL);
18662 assert(cons != NULL);
18663 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18664
18665 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18666 {
18667 SCIPerrorMessage("constraint is not linear\n");
18668 SCIPABORT();
18669 return SCIP_INVALID; /*lint !e527*/
18670 }
18671
18672 consdata = SCIPconsGetData(cons);
18673 assert(consdata != NULL);
18674
18675 if( consdata->row != NULL )
18676 return SCIProwGetDualsol(consdata->row);
18677 else
18678 return 0.0;
18679}
18680
18681/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18683 SCIP* scip, /**< SCIP data structure */
18684 SCIP_CONS* cons /**< constraint data */
18685 )
18686{
18687 SCIP_CONSDATA* consdata;
18688
18689 assert(scip != NULL);
18690 assert(cons != NULL);
18691 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18692
18693 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18694 {
18695 SCIPerrorMessage("constraint is not linear\n");
18696 SCIPABORT();
18697 return SCIP_INVALID; /*lint !e527*/
18698 }
18699
18700 consdata = SCIPconsGetData(cons);
18701 assert(consdata != NULL);
18702
18703 if( consdata->row != NULL )
18704 return SCIProwGetDualfarkas(consdata->row);
18705 else
18706 return 0.0;
18707}
18708
18709/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18710 * the user must not modify the row!
18711 */
18713 SCIP* scip, /**< SCIP data structure */
18714 SCIP_CONS* cons /**< constraint data */
18715 )
18716{
18717 SCIP_CONSDATA* consdata;
18718
18719 assert(scip != NULL);
18720 assert(cons != NULL);
18721
18722 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18723 {
18724 SCIPerrorMessage("constraint is not linear\n");
18725 SCIPABORT();
18726 return NULL; /*lint !e527*/
18727 }
18728
18729 consdata = SCIPconsGetData(cons);
18730 assert(consdata != NULL);
18731
18732 return consdata->row;
18733}
18734
18735/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18737 SCIP* scip, /**< SCIP data structure */
18738 SCIP_CONS* cons, /**< source constraint to try to convert */
18739 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18740 )
18741{
18742 SCIP_CONSHDLR* conshdlr;
18743 SCIP_CONSHDLRDATA* conshdlrdata;
18744 SCIP_CONSDATA* consdata;
18745 SCIP_VAR* var;
18746 SCIP_Real val;
18747 SCIP_Real lb;
18748 SCIP_Real ub;
18749 SCIP_Real poscoeffsum;
18750 SCIP_Real negcoeffsum;
18751 SCIP_Bool infeasible;
18752 SCIP_Bool integral;
18753 int nchgsides = 0;
18754 int nposbin;
18755 int nnegbin;
18756 int nposint;
18757 int nnegint;
18758 int nposimpl;
18759 int nnegimpl;
18760 int nposimplbin;
18761 int nnegimplbin;
18762 int nposcont;
18763 int nnegcont;
18764 int ncoeffspone;
18765 int ncoeffsnone;
18766 int ncoeffspint;
18767 int ncoeffsnint;
18768 int ncoeffspfrac;
18769 int ncoeffsnfrac;
18770 int i;
18771
18772 assert(scip != NULL);
18773 assert(cons != NULL);
18774 assert(upgdcons != NULL);
18775
18776 *upgdcons = NULL;
18777
18778 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18779 if( SCIPconsIsModifiable(cons) )
18780 return SCIP_OKAY;
18781
18782 /* check for upgradability */
18783 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18784 return SCIP_OKAY;
18785
18786 /* get the constraint handler and check, if it's really a linear constraint */
18787 conshdlr = SCIPconsGetHdlr(cons);
18788 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18789 {
18790 SCIPerrorMessage("constraint is not linear\n");
18791 return SCIP_INVALIDDATA;
18792 }
18793
18794 /* get constraint handler data and constraint data */
18795 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18796 assert(conshdlrdata != NULL);
18797 consdata = SCIPconsGetData(cons);
18798 assert(consdata != NULL);
18799
18800 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18801 if( consdata->upgraded )
18802 return SCIP_OKAY;
18803
18804 /* check, if the constraint is already stored as LP row */
18805 if( consdata->row != NULL )
18806 {
18807 if( SCIProwIsInLP(consdata->row) )
18808 {
18809 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18810 return SCIP_INVALIDDATA;
18811 }
18812 else
18813 {
18814 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18815 }
18816 }
18817
18818 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18819
18820 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18821 * skipped and we hope that the infeasibility gets detected later again.
18822 *
18823 * TODO: do we want to try to upgrade the constraint anyway?
18824 *
18825 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18826 * proven to be infeasible.
18827 */
18828 if( infeasible ) /*lint !e774*/
18829 return SCIP_OKAY;
18830
18831 /* tighten sides */
18832 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18833
18834 if( infeasible ) /*lint !e774*/
18835 return SCIP_OKAY;
18836
18837 /*
18838 * calculate some statistics on linear constraint
18839 */
18840
18841 nposbin = 0;
18842 nnegbin = 0;
18843 nposint = 0;
18844 nnegint = 0;
18845 nposimpl = 0;
18846 nnegimpl = 0;
18847 nposimplbin = 0;
18848 nnegimplbin = 0;
18849 nposcont = 0;
18850 nnegcont = 0;
18851 ncoeffspone = 0;
18852 ncoeffsnone = 0;
18853 ncoeffspint = 0;
18854 ncoeffsnint = 0;
18855 ncoeffspfrac = 0;
18856 ncoeffsnfrac = 0;
18857 integral = TRUE;
18858 poscoeffsum = 0.0;
18859 negcoeffsum = 0.0;
18860
18861 for( i = 0; i < consdata->nvars; ++i )
18862 {
18863 var = consdata->vars[i];
18864 val = consdata->vals[i];
18865 lb = SCIPvarGetLbLocal(var);
18866 ub = SCIPvarGetUbLocal(var);
18867 assert(!SCIPisZero(scip, val));
18868
18869 switch( SCIPvarGetType(var) )
18870 {
18872 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18873 integral = integral && SCIPisIntegral(scip, val);
18874 if( val >= 0.0 )
18875 nposbin++;
18876 else
18877 nnegbin++;
18878 break;
18880 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18881 integral = integral && SCIPisIntegral(scip, val);
18882 if( val >= 0.0 )
18883 nposint++;
18884 else
18885 nnegint++;
18886 break;
18888 if( SCIPvarIsBinary(var) )
18889 {
18890 if( val >= 0.0 )
18891 nposimplbin++;
18892 else
18893 nnegimplbin++;
18894 }
18895 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18896 integral = integral && SCIPisIntegral(scip, val);
18897 if( val >= 0.0 )
18898 nposimpl++;
18899 else
18900 nnegimpl++;
18901 break;
18903 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18904 if( val >= 0.0 )
18905 nposcont++;
18906 else
18907 nnegcont++;
18908 break;
18909 default:
18910 SCIPerrorMessage("unknown variable type\n");
18911 return SCIP_INVALIDDATA;
18912 }
18913 if( SCIPisEQ(scip, val, 1.0) )
18914 ncoeffspone++;
18915 else if( SCIPisEQ(scip, val, -1.0) )
18916 ncoeffsnone++;
18917 else if( SCIPisIntegral(scip, val) )
18918 {
18919 if( SCIPisPositive(scip, val) )
18920 ncoeffspint++;
18921 else
18922 ncoeffsnint++;
18923 }
18924 else
18925 {
18926 if( SCIPisPositive(scip, val) )
18927 ncoeffspfrac++;
18928 else
18929 ncoeffsnfrac++;
18930 }
18931 if( SCIPisPositive(scip, val) )
18932 poscoeffsum += val;
18933 else
18934 negcoeffsum += val;
18935 }
18936
18937 /*
18938 * call the upgrading methods
18939 */
18940
18941 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18942 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18943 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",
18944 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18945 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18946 poscoeffsum, negcoeffsum, integral);
18947
18948 /* try all upgrading methods in priority order in case the upgrading step is enable */
18949 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18950 {
18951 if( conshdlrdata->linconsupgrades[i]->active )
18952 {
18953 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18954 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18955 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18956 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18957 poscoeffsum, negcoeffsum, integral,
18958 upgdcons) );
18959 }
18960 }
18961
18962#ifdef SCIP_DEBUG
18963 if( *upgdcons != NULL )
18964 {
18966 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18967 SCIPdebugPrintCons(scip, *upgdcons, NULL);
18968 }
18969#endif
18970
18971 return SCIP_OKAY; /*lint !e438*/
18972}
18973
18974/** cleans up (multi-)aggregations and fixings from linear constraints */
18976 SCIP* scip, /**< SCIP data structure */
18977 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18978 SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
18979 )
18980{
18981 SCIP_CONSHDLR* conshdlr;
18982 SCIP_CONS** conss;
18983 int nconss;
18984 int i;
18985
18986 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18987 if( conshdlr == NULL )
18988 return SCIP_OKAY;
18989
18990 assert(infeasible != NULL);
18991 *infeasible = FALSE;
18992
18993 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
18994 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
18995
18996 for( i = 0; i < nconss; ++i )
18997 {
18998 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
18999
19000 if( *infeasible )
19001 break;
19002 }
19003
19004 return SCIP_OKAY;
19005}
static long bound
SCIP_VAR * w
Definition: circlepacking.c:67
SCIP_VAR * a
Definition: circlepacking.c:66
SCIP_VAR ** b
Definition: circlepacking.c:65
SCIP_VAR ** x
Definition: circlepacking.c:63
enum Proprule PROPRULE
Definition: cons_and.c:179
Proprule
Definition: cons_and.c:172
struct InferInfo INFERINFO
Constraint handler for knapsack constraints of the form , x binary and .
#define MAX_CLIQUE_NONZEROS_PER_CONS
Definition: cons_linear.c:7858
enum Proprule PROPRULE
Definition: cons_linear.c:355
static SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3670
#define DEFAULT_AGGREGATEVARIABLES
Definition: cons_linear.c:142
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linear.c:1101
#define DEFAULT_NMINCOMPARISONS
Definition: cons_linear.c:127
#define DEFAULT_MULTAGGRREMOVE
Definition: cons_linear.c:161
#define DEFAULT_DUALPRESOLVING
Definition: cons_linear.c:144
#define DEFAULT_EXTRACTCLIQUES
Definition: cons_linear.c:165
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3269
#define CONSHDLR_NEEDSCONS
Definition: cons_linear.c:108
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1548
#define CONSHDLR_SEPAFREQ
Definition: cons_linear.c:101
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool checkrelmaxabs, SCIP_Bool *violated)
Definition: cons_linear.c:7169
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7453
#define CONFLICTHDLR_PRIORITY
Definition: cons_linear.c:118
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
Definition: cons_linear.c:2586
static SCIP_DECL_EVENTEXEC(eventExecLinear)
static SCIP_RETCODE convertEquality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgvartypes)
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define CONFLICTHDLR_NAME
Definition: cons_linear.c:116
#define MAXDNOM
Definition: cons_linear.c:167
static SCIP_RETCODE conshdlrdataIncludeUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_LINCONSUPGRADE *linconsupgrade)
Definition: cons_linear.c:619
static SCIP_RETCODE extractCliques(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, int *nfixedvars, int *nchgbds, SCIP_Bool *cutoff)
Definition: cons_linear.c:7925
static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
#define CONSHDLR_CHECKPRIORITY
Definition: cons_linear.c:100
#define CONSHDLR_DESC
Definition: cons_linear.c:97
static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7429
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
Definition: cons_linear.c:3160
static int getVarWeight(SCIP_VAR *var)
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9496
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1311
static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
static SCIP_DECL_CONSPRESOL(consPresolLinear)
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
Definition: cons_linear.c:4990
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
static SCIP_DECL_CONSFREE(consFreeLinear)
#define DEFAULT_DETECTCUTOFFBOUND
Definition: cons_linear.c:148
static SCIP_RETCODE tightenVarLb(SCIP *scip, SCIP_CONS *cons, int pos, PROPRULE proprule, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5321
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds, int *nchgvartypes)
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss, int *nchgvartypes)
Definition: cons_linear.c:9608
static SCIP_DECL_CONSINITLP(consInitlpLinear)
#define CONSHDLR_PROP_TIMING
Definition: cons_linear.c:111
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1258
static SCIP_DECL_CONSPARSE(consParseLinear)
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:448
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
static SCIP_RETCODE retrieveParallelConstraints(SCIP_HASHTABLE *hashtable, SCIP_CONS **querycons, SCIP_CONS **parallelconss, int *nparallelconss)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:117
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linear.c:567
static void calculateMinvalAndMaxval(SCIP *scip, SCIP_Real side, SCIP_Real val, SCIP_Real minresactivity, SCIP_Real maxresactivity, SCIP_Real *minval, SCIP_Real *maxval)
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:651
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1365
static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
static void consdataUpdateActivitiesUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2027
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
Definition: cons_linear.c:8898
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2052
static void consdataUpdateActivitiesLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2002
#define CONSHDLR_MAXPREROUNDS
Definition: cons_linear.c:105
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
Definition: cons_linear.c:589
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
Definition: cons_linear.c:3918
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1338
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
Definition: cons_linear.c:508
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_linear.c:125
#define DEFAULT_MAXAGGRNORMSCALE
Definition: cons_linear.c:134
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
Definition: cons_linear.c:4101
#define checkMaxActivityDelta(scip, consdata)
Definition: cons_linear.c:1543
static SCIP_DECL_CONSTRANS(consTransLinear)
#define CONSHDLR_SEPAPRIORITY
Definition: cons_linear.c:98
static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
#define DEFAULT_SINGLETONSTUFFING
Definition: cons_linear.c:145
#define DEFAULT_MAXROUNDSROOT
Definition: cons_linear.c:122
static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
Definition: cons_linear.c:3115
#define MINVALRECOMP
Definition: cons_linear.c:177
#define DEFAULT_MAXCARDBOUNDDIST
Definition: cons_linear.c:138
#define DEFAULT_MAXEASYACTIVITYDELTA
Definition: cons_linear.c:136
static SCIP_DECL_CONSEXIT(consExitLinear)
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
Definition: cons_linear.c:4008
static int inferInfoGetPos(INFERINFO inferinfo)
Definition: cons_linear.c:405
static SCIP_DECL_CONSPRINT(consPrintLinear)
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides)
#define DEFAULT_CHECKRELMAXABS
Definition: cons_linear.c:132
#define DEFAULT_MAXDUALMULTAGGRQUOT
Definition: cons_linear.c:164
static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
Definition: cons_linear.c:529
static SCIP_RETCODE aggregateConstraints(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, int *commonidx0, int *commonidx1, int *diffidx0minus1, int *diffidx1minus0, int nvarscommon, int commonidxweight, int diffidx0minus1weight, int diffidx1minus0weight, SCIP_Real maxaggrnormscale, int *nchgcoefs, SCIP_Bool *aggregated, SCIP_Bool *infeasible)
static SCIP_DECL_CONSENFOPS(consEnfopsLinear)
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:5199
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
Definition: cons_linear.c:5726
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:374
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4480
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_SOL *sol, SCIP_Bool separatecards, SCIP_Bool separateall, int *ncuts, SCIP_Bool *cutoff)
Definition: cons_linear.c:7552
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2539
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1472
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
Definition: cons_linear.c:3412
static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
#define DEFAULT_SORTVARS
Definition: cons_linear.c:130
#define DEFAULT_MAXMULTAGGRQUOT
Definition: cons_linear.c:163
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2075
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:718
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1443
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:4808
#define MAXCONSPRESOLROUNDS
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_linear.c:473
#define MAXACTVAL
Definition: cons_linear.c:172
#define NONLINCONSUPGD_PRIORITY
Definition: cons_linear.c:180
#define DEFAULT_MAXSEPACUTSROOT
Definition: cons_linear.c:124
@ PROPRULE_1_RANGEDROW
Definition: cons_linear.c:351
@ PROPRULE_1_LHS
Definition: cons_linear.c:349
@ PROPRULE_INVALID
Definition: cons_linear.c:353
@ PROPRULE_1_RHS
Definition: cons_linear.c:347
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:6991
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1419
#define DEFAULT_RANGEDROWPROPAGATION
Definition: cons_linear.c:156
static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:823
static SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_linear.c:126
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3026
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:9020
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4160
static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
static SCIP_RETCODE presolStuffing(SCIP *scip, SCIP_CONS *cons, SCIP_Bool singletonstuffing, SCIP_Bool singlevarstuffing, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds)
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:684
static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3140
static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5055
static SCIP_DECL_CONSINIT(consInitLinear)
#define DEFAULT_RANGEDROWFREQ
Definition: cons_linear.c:159
static SCIP_DECL_CONSDELETE(consDeleteLinear)
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool tightenbounds, SCIP_Bool rangedrowpropagation, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:7642
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2174
#define DEFAULT_RANGEDROWARTCONS
Definition: cons_linear.c:157
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3805
#define MAXSCALEDCOEFINTEGER
Definition: cons_linear.c:169
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2098
static void getMinActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Bool *istight, SCIP_Bool *issettoinfinity)
Definition: cons_linear.c:2351
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
Definition: cons_linear.c:854
static SCIP_DECL_CONSACTIVE(consActiveLinear)
#define BINWEIGHT
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
Definition: cons_linear.c:3540
static SCIP_DECL_CONSCHECK(consCheckLinear)
#define DEFAULT_SIMPLIFYINEQUALITIES
Definition: cons_linear.c:143
static SCIP_DECL_CONSSEPALP(consSepalpLinear)
#define CONSHDLR_PROPFREQ
Definition: cons_linear.c:102
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5391
static void consdataUpdateActivities(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_Real val, SCIP_BOUNDTYPE boundtype, SCIP_Bool global, SCIP_Bool checkreliability)
Definition: cons_linear.c:1610
static unsigned int getParallelConsKey(SCIP_CONS *cons)
#define CONTWEIGHT
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:7790
#define CONSHDLR_PRESOLTIMING
Definition: cons_linear.c:110
#define DEFAULT_DETECTPARTIALOBJECTIVE
Definition: cons_linear.c:154
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linear.c:1060
static SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
#define DEFAULT_MAXSEPACUTS
Definition: cons_linear.c:123
static void consdataGetActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2667
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2255
static SCIP_DECL_CONSINITSOL(consInitsolLinear)
static SCIP_DECL_CONSRESPROP(consRespropLinear)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7516
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
Definition: cons_linear.c:1140
#define CONSHDLR_EAGERFREQ
Definition: cons_linear.c:103
static void getMaxActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *maxactivity, SCIP_Bool *istight, SCIP_Bool *issettoinfinity)
Definition: cons_linear.c:2446
#define DEFAULT_TIGHTENBOUNDSFREQ
Definition: cons_linear.c:120
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
Definition: cons_linear.c:9554
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9440
static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
Definition: cons_linear.c:2239
#define EVENTHDLR_DESC
Definition: cons_linear.c:114
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:543
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1392
static SCIP_DECL_CONSPROP(consPropLinear)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4543
static SCIP_DECL_CONSLOCK(consLockLinear)
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2289
#define DEFAULT_MAXROUNDS
Definition: cons_linear.c:121
static void consdataGetGlbActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2876
#define CONSHDLR_ENFOPRIORITY
Definition: cons_linear.c:99
static SCIP_RETCODE tightenVarUb(SCIP *scip, SCIP_CONS *cons, int pos, PROPRULE proprule, SCIP_Real newub, SCIP_Real oldub, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5251
static int getInferInt(PROPRULE proprule, int pos)
Definition: cons_linear.c:433
static int inferInfoGetProprule(INFERINFO inferinfo)
Definition: cons_linear.c:396
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgvartypes)
#define DEFAULT_MINGAINPERNMINCOMP
Definition: cons_linear.c:128
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3094
static SCIP_RETCODE rangedRowSimplify(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars)
#define CONSHDLR_DELAYSEPA
Definition: cons_linear.c:106
static SCIP_DECL_CONSCOPY(consCopyLinear)
#define MAXSCALEDCOEF
Definition: cons_linear.c:168
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1212
#define DEFAULT_RANGEDROWMAXDEPTH
Definition: cons_linear.c:158
static SCIP_RETCODE analyzeConflictRangedRow(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5668
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:757
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:6711
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2271
#define CONSHDLR_NAME
Definition: cons_linear.c:96
static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
static int inferInfoToInt(INFERINFO inferinfo)
Definition: cons_linear.c:387
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Real maxaggrnormscale, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides, int *nchgcoefs)
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3345
#define DEFAULT_SINGLEVARSTUFFING
Definition: cons_linear.c:146
#define EVENTHDLR_NAME
Definition: cons_linear.c:113
#define INTWEIGHT
static SCIP_RETCODE checkParallelObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides, SCIP_Bool *infeasible)
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:791
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, INFERINFO inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
Definition: cons_linear.c:5106
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:151
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
#define MAXVALRECOMP
Definition: cons_linear.c:176
#define CONSHDLR_DELAYPROP
Definition: cons_linear.c:107
static void consdataGetGlbActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *glbminactivity, SCIP_Real *glbmaxactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2816
static SCIP_Bool canTightenBounds(SCIP_CONS *cons)
Definition: cons_linear.c:5223
#define DEFAULT_SEPARATEALL
Definition: cons_linear.c:140
static void findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Definition: cons_linear.c:414
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:6987
Constraint handler for linear constraints in their most general form, .
constraint handler for nonlinear constraints specified by algebraic expressions
defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
#define QUAD_MEMBER(x)
Definition: dbldblarith.h:48
#define SCIPquadprecSumQD(r, a, b)
Definition: dbldblarith.h:62
#define QUAD_ASSIGN(a, constant)
Definition: dbldblarith.h:51
#define QUAD(x)
Definition: dbldblarith.h:47
#define QUAD_ASSIGN_Q(a, b)
Definition: dbldblarith.h:52
#define QUAD_TO_DBL(x)
Definition: dbldblarith.h:49
methods for debugging
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:299
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:298
#define NULL
Definition: def.h:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#define COPYSIGN
Definition: def.h:257
#define SCIP_Longint
Definition: def.h:157
#define SCIP_MAXTREEDEPTH
Definition: def.h:315
#define SCIP_REAL_MAX
Definition: def.h:173
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:242
#define MAX3(x, y, z)
Definition: def.h:246
#define SCIP_Real
Definition: def.h:172
#define ABS(x)
Definition: def.h:234
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL_ABORT(x)
Definition: def.h:352
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define MIN3(x, y, z)
Definition: def.h:250
#define SCIPABORT()
Definition: def.h:345
#define REALABS(x)
Definition: def.h:196
#define EPSGT(x, y, eps)
Definition: def.h:200
#define SCIP_CALL(x)
Definition: def.h:373
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_RETCODE SCIPincludeConsUpgradeNonlinear(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nlconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts)
SCIP_Real SCIPgetRhsNonlinear(SCIP_CONS *cons)
SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
#define SCIP_DECL_LINCONSUPGD(x)
Definition: cons_linear.h:120
SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
SCIP_RETCODE SCIPcleanupConssLinear(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_Real SCIPgetFeasibilityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip_copy.c:2068
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip_copy.c:660
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip_copy.c:711
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:606
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip_general.c:643
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:734
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:390
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2220
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1668
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2172
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3089
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1268
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2843
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3043
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2349
#define SCIPhashFour(a, b, c, d)
Definition: pub_misc.h:556
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2582
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2299
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2611
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2807
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2680
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2550
#define SCIPhashSignature64(a)
Definition: pub_misc.h:549
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip_prob.c:3697
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3475
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:3586
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3229
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3394
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsgPrint
Definition: scip_message.h:79
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:88
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9124
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9376
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9397
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9827
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11215
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:83
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:139
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:57
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:269
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10399
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c: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:4656
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:808
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4227
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4613
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:540
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip_cons.c:396
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:831
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip_cons.c:235
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:281
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip_cons.c:181
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip_cons.c:693
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
Definition: scip_cons.c:900
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:323
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5140
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4636
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4197
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip_cons.c:420
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:516
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:941
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
Definition: scip_cons.c:924
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip_cons.c:468
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip_cons.c:762
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:624
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip_cons.c:444
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4217
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:647
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4670
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:854
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4593
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip_cons.c:670
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:785
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8244
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:8224
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8473
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8234
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8383
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2537
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8665
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip_cons.c:1297
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8423
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8513
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8413
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8343
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8523
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8563
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip_cons.c:1272
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition: scip_cons.c:1322
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition: cons.c:8607
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8403
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2043
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8275
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip_cons.c:998
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8433
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8453
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8573
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8214
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8553
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1813
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2015
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8463
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip_cons.c:1525
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8493
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1174
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip_cons.c:1372
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition: scip_cons.c:1347
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8393
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1785
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8483
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:250
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c: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:3860
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:3870
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1567
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:416
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:83
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:105
SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:424
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:396
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip_nlp.c:1058
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition: nlp.c:1956
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition: scip_nlp.c:954
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:97
void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
Definition: cons.c:8108
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition: cons.c:8076
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17439
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1583
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1422
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1701
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2212
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2167
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1562
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17353
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1607
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17551
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_lp.c:1727
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17340
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2144
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1213
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:137
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
int SCIPgetNSepaRounds(SCIP *scip)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
int SCIPgetNRuns(SCIP *scip)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Real SCIPgetHugeValue(SCIP *scip)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip_tree.c:146
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17647
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:12801
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17667
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:17909
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18217
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17921
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17775
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17626
SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip_var.c:7044
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1480
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17565
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3353
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip_var.c:8676
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18171
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8709
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17588
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:8512
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5738
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17953
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:17611
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:18115
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17785
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:17795
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17446
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:8646
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18707
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:17637
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8299
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1693
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17885
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17873
SCIP_RETCODE SCIPaddVarImplication(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip_var.c:6903
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17657
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18161
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17601
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17733
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:17575
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18105
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8399
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5624
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:1992
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11969
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:18697
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:8740
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:17897
void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5541
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10880
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10869
SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
SCIP_RETCODE SCIPextendPermsymDetectionGraphLinear(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool *success)
static const SCIP_Real scalars[]
Definition: lp.c:5741
static const char * paramname[]
Definition: lpi_msk.c:5103
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
public methods for conflict analysis handlers
public methods for managing constraints
public methods for managing events
public functions to work with algebraic expressions
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPstatisticMessage
Definition: pub_message.h:123
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
#define SCIPdebugMessage
Definition: pub_message.h:96
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for problem variables
public methods for branching rule plugins and branching
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for cuts and aggregation rows
public methods for event handler plugins and event handlers
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
SCIP_DECL_LINCONSUPGD((*linconsupgd))
structs for symmetry computations
methods for dealing with symmetry detection graphs
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:60
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:64
@ SCIP_LINCONSTYPE_BINPACKING
Definition: type_cons.h:85
@ SCIP_LINCONSTYPE_VARBOUND
Definition: type_cons.h:78
@ SCIP_LINCONSTYPE_EMPTY
Definition: type_cons.h:73
@ SCIP_LINCONSTYPE_INVKNAPSACK
Definition: type_cons.h:83
@ SCIP_LINCONSTYPE_PRECEDENCE
Definition: type_cons.h:77
@ SCIP_LINCONSTYPE_AGGREGATION
Definition: type_cons.h:76
@ SCIP_LINCONSTYPE_MIXEDBINARY
Definition: type_cons.h:88
@ SCIP_LINCONSTYPE_SINGLETON
Definition: type_cons.h:75
@ SCIP_LINCONSTYPE_SETCOVERING
Definition: type_cons.h:81
@ SCIP_LINCONSTYPE_EQKNAPSACK
Definition: type_cons.h:84
@ SCIP_LINCONSTYPE_FREE
Definition: type_cons.h:74
@ SCIP_LINCONSTYPE_KNAPSACK
Definition: type_cons.h:86
@ SCIP_LINCONSTYPE_SETPARTITION
Definition: type_cons.h:79
@ SCIP_LINCONSTYPE_INTKNAPSACK
Definition: type_cons.h:87
@ SCIP_LINCONSTYPE_SETPACKING
Definition: type_cons.h:80
@ SCIP_LINCONSTYPE_GENERAL
Definition: type_cons.h:89
@ SCIP_LINCONSTYPE_CARDINALITY
Definition: type_cons.h:82
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition: type_cons.h:91
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:125
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:73
#define SCIP_EVENTTYPE_TYPECHANGED
Definition: type_event.h:86
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:76
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:120
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:79
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:72
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:71
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:152
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:75
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:124
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:121
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:122
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:151
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:123
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:77
@ SCIP_EXPRCURV_LINEAR
Definition: type_expr.h:65
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:57
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
@ SCIP_VERBLEVEL_HIGH
Definition: type_message.h:56
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_FEASIBLE
Definition: type_result.h:45
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_CONSADDED
Definition: type_result.h:52
@ SCIP_SEPARATED
Definition: type_result.h:49
@ SCIP_SUCCESS
Definition: type_result.h:58
@ SCIP_INFEASIBLE
Definition: type_result.h:46
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_READERROR
Definition: type_retcode.h:45
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PROBLEM
Definition: type_set.h:45
@ SCIP_STAGE_INITSOLVE
Definition: type_set.h:52
@ SCIP_STAGE_EXITPRESOLVE
Definition: type_set.h:50
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition: type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition: type_set.h:51
enum SYM_Symtype SYM_SYMTYPE
Definition: type_symmetry.h:64
@ SYM_SYMTYPE_SIGNPERM
Definition: type_symmetry.h:62
@ SYM_SYMTYPE_PERM
Definition: type_symmetry.h:61
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:54
#define NLOCKTYPES
Definition: type_var.h:94
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:63
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_IMPLINT
Definition: type_var.h:64
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:62
@ SCIP_VARSTATUS_ORIGINAL
Definition: type_var.h:49
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:52
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:51
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:54
@ SCIP_VARSTATUS_NEGATED
Definition: type_var.h:55
@ SCIP_VARSTATUS_AGGREGATED
Definition: type_var.h:53
@ SCIP_VARSTATUS_LOOSE
Definition: type_var.h:50
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:100
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:97
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:57