Scippy

SCIP

Solving Constraint Integer Programs

cons_linear.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file cons_linear.c
26 * @ingroup DEFPLUGINS_CONS
27 * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Marc Pfetsch
31 * @author Kati Wolter
32 * @author Michael Winkler
33 * @author Gerald Gamrath
34 * @author Domenico Salvagnin
35 *
36 * Linear constraints are separated with a high priority, because they are easy
37 * to separate. Instead of using the global cut pool, the same effect can be
38 * implemented by adding linear constraints to the root node, such that they are
39 * separated each time, the linear constraints are separated. A constraint
40 * handler, which generates linear constraints in this way should have a lower
41 * separation priority than the linear constraint handler, and it should have a
42 * separation frequency that is a multiple of the frequency of the linear
43 * constraint handler. In this way, it can be avoided to separate the same cut
44 * twice, because if a separation run of the handler is always preceded by a
45 * separation of the linear constraints, the priorily added constraints are
46 * always satisfied.
47 *
48 * Linear constraints are enforced and checked with a very low priority. Checking
49 * of (many) linear constraints is much more involved than checking the solution
50 * values for integrality. Because we are separating the linear constraints quite
51 * often, it is only necessary to enforce them for integral solutions. A constraint
52 * handler which generates pool cuts in its enforcing method should have an
53 * enforcing priority smaller than that of the linear constraint handler to avoid
54 * regenerating constraints which already exist.
55 */
56
57/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
58
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 SCIP_VAR* var;
4553 SCIP_VAR** aggrvars;
4554 SCIP_Real val;
4555 SCIP_Real* aggrscalars;
4556 SCIP_Real fixedval;
4557 SCIP_Real aggrconst;
4558 int v;
4559 int naggrvars;
4560 int i;
4561
4562 assert(scip != NULL);
4563 assert(cons != NULL);
4564
4565 if( infeasible != NULL )
4566 *infeasible = FALSE;
4567
4568 consdata = SCIPconsGetData(cons);
4569 assert(consdata != NULL);
4570
4571 if( consdata->eventdata == NULL )
4572 {
4573 SCIP_CONSHDLR* conshdlr;
4574 SCIP_CONSHDLRDATA* conshdlrdata;
4575
4576 conshdlr = SCIPconsGetHdlr(cons);
4577 assert(conshdlr != NULL);
4578
4579 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4580 assert(conshdlrdata != NULL);
4581
4582 /* catch bound change events of variables */
4583 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4584 assert(consdata->eventdata != NULL);
4585 }
4586
4587 if( !consdata->removedfixings )
4588 {
4589 SCIP_Real lhssubtrahend;
4590 SCIP_Real rhssubtrahend;
4591
4592 /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4593 * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4594 */
4595 assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4596
4597 lhssubtrahend = 0.0;
4598 rhssubtrahend = 0.0;
4599
4600 SCIPdebugMsg(scip, "applying fixings:\n");
4602
4603 v = 0;
4604 while( v < consdata->nvars )
4605 {
4606 var = consdata->vars[v];
4607 val = consdata->vals[v];
4608 assert(SCIPvarIsTransformed(var));
4609
4610 switch( SCIPvarGetStatus(var) )
4611 {
4613 SCIPerrorMessage("original variable in transformed linear constraint\n");
4614 return SCIP_INVALIDDATA;
4615
4618 ++v;
4619 break;
4620
4623 fixedval = SCIPvarGetLbGlobal(var);
4624 if( !SCIPisInfinity(scip, -consdata->lhs) )
4625 {
4626 if( SCIPisInfinity(scip, ABS(fixedval)) )
4627 {
4628 /* if lhs gets infinity it means that the problem is infeasible */
4629 if( ( val > 0.0 ) != ( fixedval > 0.0 ) )
4630 {
4632
4633 if( infeasible != NULL )
4634 {
4635 *infeasible = TRUE;
4636 return SCIP_OKAY;
4637 }
4638 }
4639 else
4640 {
4641 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4642 }
4643 }
4644 else
4645 lhssubtrahend += val * fixedval;
4646 }
4647 if( !SCIPisInfinity(scip, consdata->rhs) )
4648 {
4649 if( SCIPisInfinity(scip, ABS(fixedval)) )
4650 {
4651 /* if rhs gets -infinity it means that the problem is infeasible */
4652 if( ( val > 0.0 ) == ( fixedval > 0.0 ) )
4653 {
4654 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4655
4656 if( infeasible != NULL )
4657 {
4658 *infeasible = TRUE;
4659 return SCIP_OKAY;
4660 }
4661 }
4662 else
4663 {
4665 }
4666 }
4667 else
4668 rhssubtrahend += val * fixedval;
4669 }
4670 SCIP_CALL( delCoefPos(scip, cons, v) );
4671 break;
4672
4674 {
4675 SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4676 SCIP_Real activescalar = SCIPvarGetAggrScalar(var);
4677 SCIP_Real activeconstant = SCIPvarGetAggrConstant(var);
4678
4679 assert(activevar != NULL);
4680 SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4681 assert(activevar != NULL);
4682 SCIP_CALL( addCoef(scip, cons, activevar, val * activescalar) );
4683
4684 if( activeconstant != 0.0 )
4685 {
4686 if( !SCIPisInfinity(scip, -consdata->lhs) )
4687 lhssubtrahend += val * activeconstant;
4688 if( !SCIPisInfinity(scip, consdata->rhs) )
4689 rhssubtrahend += val * activeconstant;
4690 }
4691
4692 SCIP_CALL( delCoefPos(scip, cons, v) );
4693 break;
4694 }
4697 naggrvars = SCIPvarGetMultaggrNVars(var);
4698 aggrvars = SCIPvarGetMultaggrVars(var);
4699 aggrscalars = SCIPvarGetMultaggrScalars(var);
4700 aggrconst = SCIPvarGetMultaggrConstant(var);
4701
4702 for( i = 0; i < naggrvars; ++i )
4703 {
4704 SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4705 }
4706
4707 if( aggrconst != 0.0 )
4708 {
4709 if( !SCIPisInfinity(scip, -consdata->lhs) )
4710 lhssubtrahend += val * aggrconst;
4711 if( !SCIPisInfinity(scip, consdata->rhs) )
4712 rhssubtrahend += val * aggrconst;
4713 }
4714
4715 SCIP_CALL( delCoefPos(scip, cons, v) );
4716 break;
4717
4719 SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4720 aggrconst = SCIPvarGetNegationConstant(var);
4721
4722 if( !SCIPisInfinity(scip, -consdata->lhs) )
4723 lhssubtrahend += val * aggrconst;
4724 if( !SCIPisInfinity(scip, consdata->rhs) )
4725 rhssubtrahend += val * aggrconst;
4726
4727 SCIP_CALL( delCoefPos(scip, cons, v) );
4728 break;
4729
4730 default:
4731 SCIPerrorMessage("unknown variable status\n");
4732 SCIPABORT();
4733 return SCIP_INVALIDDATA; /*lint !e527*/
4734 }
4735 }
4736
4737 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4738 {
4739 /* check left hand side of unmodifiable empty constraint with former feasibility tolerance */
4740 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4741 {
4742 if( SCIPisFeasLT(scip, lhssubtrahend, consdata->lhs) )
4743 {
4745
4746 if( infeasible != NULL )
4747 {
4748 *infeasible = TRUE;
4749 return SCIP_OKAY;
4750 }
4751 }
4752 else
4753 {
4754 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4755 }
4756 }
4757 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
4758 * causing wrong fixings of other variables --> better use a real zero here
4759 */
4760 else if( SCIPisGE(scip, ABS(consdata->lhs), 1.0) && SCIPisEQ(scip, lhssubtrahend, consdata->lhs) )
4761 {
4762 SCIP_CALL( chgLhs(scip, cons, 0.0) );
4763 }
4764 else
4765 {
4766 SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4767 }
4768 }
4769 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs) )
4770 {
4771 /* check right hand side of unmodifiable empty constraint with former feasibility tolerance */
4772 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4773 {
4774 if( SCIPisFeasGT(scip, rhssubtrahend, consdata->rhs) )
4775 {
4776 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4777
4778 if( infeasible != NULL )
4779 {
4780 *infeasible = TRUE;
4781 return SCIP_OKAY;
4782 }
4783 }
4784 else
4785 {
4787 }
4788 }
4789 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
4790 * causing wrong fixings of other variables --> better use a real zero here
4791 */
4792 else if( SCIPisGE(scip, ABS(consdata->rhs), 1.0) && SCIPisEQ(scip, rhssubtrahend, consdata->rhs) )
4793 {
4794 SCIP_CALL( chgRhs(scip, cons, 0.0) );
4795 }
4796 else
4797 {
4798 SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4799 }
4800 }
4801 consdata->removedfixings = TRUE;
4802
4803 SCIPdebugMsg(scip, "after fixings:\n");
4805
4806 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4807 * to clean up the constraint
4808 */
4809 SCIP_CALL( mergeMultiples(scip, cons) );
4810
4811 SCIPdebugMsg(scip, "after merging:\n");
4813 }
4814 assert(consdata->removedfixings);
4815
4816#ifndef NDEBUG
4817 /* check, if all fixings are applied */
4818 for( v = 0; v < consdata->nvars; ++v )
4819 assert(SCIPvarIsActive(consdata->vars[v]));
4820#endif
4821
4822 return SCIP_OKAY;
4823}
4824
4825/** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4826 * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4827 * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4828 * conflict detecting constraint by using NULL as inferred variable
4829 */
4830static
4832 SCIP* scip, /**< SCIP data structure */
4833 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4834 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4835 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4836 int inferpos, /**< position of the inferred variable in the vars array */
4837 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4838 )
4839{
4840 SCIP_CONSDATA* consdata;
4841 SCIP_VAR** vars;
4842 SCIP_Real* vals;
4843 int nvars;
4844 int i;
4845
4846 assert(scip != NULL);
4847 assert(cons != NULL);
4848
4849 consdata = SCIPconsGetData(cons);
4850
4851 assert(consdata != NULL);
4852
4853 vars = consdata->vars;
4854 vals = consdata->vals;
4855 nvars = consdata->nvars;
4856
4857 assert(vars != NULL || nvars == 0);
4858 assert(vals != NULL || nvars == 0);
4859
4860 assert(-1 <= inferpos && inferpos < nvars);
4861 assert((infervar == NULL) == (inferpos == -1));
4862 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4863
4864 /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4865 * residual value, depending on whether the left or right hand side is responsible for the bound change:
4866 * - if the right hand side is the reason, the minimal residual activity is responsible
4867 * - if the left hand side is the reason, the maximal residual activity is responsible
4868 */
4869
4870 /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4871 if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4872 {
4873 SCIP_Real minresactivity;
4874 SCIP_Real maxresactivity;
4875 SCIP_Bool ismintight;
4876 SCIP_Bool ismaxtight;
4877 SCIP_Bool isminsettoinfinity;
4878 SCIP_Bool ismaxsettoinfinity;
4879
4880 minresactivity = -SCIPinfinity(scip);
4881 maxresactivity = SCIPinfinity(scip);
4882
4883 /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4884 if( infervar != NULL )
4885 {
4886 assert(vals != NULL); /* for flexelint */
4887 if( reasonisrhs )
4888 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4889 &ismintight, NULL, &isminsettoinfinity, NULL);
4890 else
4891 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4892 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4893 }
4894 else
4895 {
4896 if( reasonisrhs )
4897 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4898 &ismintight, NULL, &isminsettoinfinity, NULL);
4899 else
4900 consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4901 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4902 }
4903
4904 /* we can only do something clever, if the residual activity is finite and not relaxed */
4905 if( (reasonisrhs && !isminsettoinfinity && ismintight) || (!reasonisrhs && !ismaxsettoinfinity && ismaxtight) ) /*lint !e644*/
4906 {
4907 SCIP_Real rescap;
4908 SCIP_Bool resactisinf;
4909
4910 resactisinf = FALSE;
4911
4912 /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4913 * than its inferred bound
4914 */
4915 if( infervar != NULL )
4916 {
4917 assert(vals != NULL); /* for flexelint */
4918
4919 if( reasonisrhs )
4920 {
4921 if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4922 {
4923 consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4924 if( SCIPisInfinity(scip, -minresactivity) )
4925 resactisinf = TRUE;
4926 }
4927 rescap = consdata->rhs - minresactivity;
4928 }
4929 else
4930 {
4931 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4932 {
4933 consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4934 if( SCIPisInfinity(scip, maxresactivity) )
4935 resactisinf = TRUE;
4936 }
4937 rescap = consdata->lhs - maxresactivity;
4938 }
4939
4940 if( reasonisrhs == (vals[inferpos] > 0.0) )
4941 rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4942 else
4943 rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
4944 }
4945 else
4946 rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4947
4948 if( !resactisinf )
4949 {
4950 /* now add bounds as reasons until the residual capacity is exceeded */
4951 for( i = 0; i < nvars; ++i )
4952 {
4953 assert( vars != NULL && vals != NULL ); /* for lint */
4954
4955 /* zero coefficients and the inferred variable can be ignored */
4956 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4957 continue;
4958
4959 /* check if the residual capacity is exceeded */
4960 if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4961 || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4962 break;
4963
4964 /* update the residual capacity due to the local bound of this variable */
4965 if( reasonisrhs == (vals[i] > 0.0) )
4966 {
4967 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4968 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4969 rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4970 }
4971 else
4972 {
4973 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4974 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4975 rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4976 }
4977 }
4978 return SCIP_OKAY;
4979 }
4980 }
4981 }
4982
4983 /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4984 for( i = 0; i < nvars; ++i )
4985 {
4986 assert(vars != NULL); /* for flexelint */
4987 assert(vals != NULL); /* for flexelint */
4988
4989 /* zero coefficients and the inferred variable can be ignored */
4990 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4991 continue;
4992
4993 if( reasonisrhs == (vals[i] > 0.0) )
4994 {
4995 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4996 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4997 }
4998 else
4999 {
5000 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
5001 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5002 }
5003 }
5004
5005 return SCIP_OKAY;
5006}
5007
5008/** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
5009 * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
5010 * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
5011 */
5012static
5014 SCIP* scip, /**< SCIP data structure */
5015 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5016 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
5017 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5018 int inferpos /**< position of the inferred variable in the vars array, or -1 */
5019 )
5020{
5021 SCIP_CONSDATA* consdata;
5022 SCIP_VAR** vars;
5023 int nvars;
5024 int v;
5025
5026 assert(scip != NULL);
5027 assert(cons != NULL);
5028
5029 consdata = SCIPconsGetData(cons);
5030 assert(consdata != NULL);
5031 vars = consdata->vars;
5032 nvars = consdata->nvars;
5033 assert(vars != NULL || nvars == 0);
5034 assert(-1 <= inferpos && inferpos < nvars);
5035 assert((infervar == NULL) == (inferpos == -1));
5036 assert(inferpos == -1 || vars != NULL);
5037 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5038
5039 /* collect all fixed variables */
5040 for( v = nvars - 1; v >= 0; --v )
5041 {
5042 assert(vars != NULL); /* for flexelint */
5043
5044 /* need to add old bounds before propagation of inferrence variable */
5045 if( vars[v] == infervar )
5046 {
5047 assert(vars[v] != NULL);
5048
5049 if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5050 {
5051 /* @todo get boundchange index before this last boundchange and correct the index */
5052 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5053 }
5054
5055 if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5056 {
5057 /* @todo get boundchange index before this last boundchange and correct the index */
5058 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5059 }
5060
5061 continue;
5062 }
5063
5064 /* check for fixed variables */
5065 if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5066 {
5067 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5068 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5069 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5070 }
5071 }
5072
5073 return SCIP_OKAY;
5074}
5075
5076/** add reasoning variables to conflict candidate queue which led to the conflict */
5077static
5079 SCIP* scip, /**< SCIP data structure */
5080 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5081 int nvars, /**< number of variables reasoning the infeasibility */
5082 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5083 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5084 )
5085{
5086 int v;
5087
5088 assert(scip != NULL);
5089
5090 /* collect all variables for which the local bounds differ from their global bounds */
5091 for( v = nvars - 1; v >= 0; --v )
5092 {
5093 assert(vars != NULL);
5094
5095 /* check for local bound changes variables */
5096 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5097 {
5098 /* add conflict bound */
5099 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5100 }
5101
5102 if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5103 {
5104 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5105 }
5106 }
5107
5108 if( var != NULL )
5109 {
5110 if( bound < SCIPvarGetLbLocal(var) )
5111 {
5112 SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5113 }
5114
5115 if( bound > SCIPvarGetUbLocal(var) )
5116 {
5117 SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5118 }
5119 }
5120
5121 return SCIP_OKAY;
5122}
5123
5124/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5125 * propagation rule (see propagateCons()):
5126 * (1) activity residuals of all other variables tighten bounds of single variable
5127 */
5128static
5130 SCIP* scip, /**< SCIP data structure */
5131 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5132 SCIP_VAR* infervar, /**< variable that was deduced */
5133 INFERINFO inferinfo, /**< inference information */
5134 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5135 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5136 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5137 )
5138{
5139 SCIP_CONSDATA* consdata;
5140 SCIP_VAR** vars;
5141#ifndef NDEBUG
5142 SCIP_Real* vals;
5143#endif
5144 int nvars;
5145 int inferpos;
5146
5147 assert(scip != NULL);
5148 assert(cons != NULL);
5149 assert(result != NULL);
5150
5151 consdata = SCIPconsGetData(cons);
5152 assert(consdata != NULL);
5153 vars = consdata->vars;
5154 nvars = consdata->nvars;
5155#ifndef NDEBUG
5156 vals = consdata->vals;
5157 assert(vars != NULL);
5158 assert(vals != NULL);
5159#endif
5160
5161 /* get the position of the inferred variable in the vars array */
5162 inferpos = inferInfoGetPos(inferinfo);
5163 if( inferpos >= nvars || vars[inferpos] != infervar )
5164 {
5165 /* find inference variable in constraint */
5166 /**@todo use a binary search here; the variables can be sorted by variable index */
5167 for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5168 {}
5169 }
5170 assert(inferpos < nvars);
5171 assert(vars[inferpos] == infervar);
5172 assert(!SCIPisZero(scip, vals[inferpos]));
5173
5174 switch( inferInfoGetProprule(inferinfo) )
5175 {
5176 case PROPRULE_1_RHS:
5177 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5178 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5179 * domain in order to not exceed the right hand side of the inequality
5180 */
5181 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5182 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5183 *result = SCIP_SUCCESS;
5184 break;
5185
5186 case PROPRULE_1_LHS:
5187 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5188 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5189 * domain in order to not fall below the left hand side of the inequality
5190 */
5191 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5192 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5193 *result = SCIP_SUCCESS;
5194 break;
5195
5197 /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5198 * the given inference variable to their bounds in this given ranged row
5199 */
5200
5201 /* check that we really have a ranged row here */
5202 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5203 SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5204 *result = SCIP_SUCCESS;
5205 break;
5206
5207 case PROPRULE_INVALID:
5208 default:
5209 SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5210 inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5211 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5212 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5213 SCIPinfoMessage(scip, NULL, ";\n");
5214 return SCIP_INVALIDDATA;
5215 }
5216
5217 return SCIP_OKAY;
5218}
5219
5220/** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5221static
5223 SCIP* scip, /**< SCIP data structure */
5224 SCIP_CONS* cons, /**< conflict detecting constraint */
5225 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5226 )
5227{
5228 /* conflict analysis can only be applied in solving stage and if it is turned on */
5230 return SCIP_OKAY;
5231
5232 /* initialize conflict analysis */
5234
5235 /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5236 SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5237
5238 /* analyze the conflict */
5240
5241 return SCIP_OKAY;
5242}
5243
5244/** check if there is any hope of tightening some bounds */
5245static
5247 SCIP_CONS* cons /**< linear constraint */
5248 )
5249{
5250 SCIP_CONSDATA* consdata;
5251 int infcountmin;
5252 int infcountmax;
5253
5254 consdata = SCIPconsGetData(cons);
5255 assert(consdata != NULL);
5256
5257 infcountmin = consdata->minactivityneginf
5258 + consdata->minactivityposinf
5259 + consdata->minactivityneghuge
5260 + consdata->minactivityposhuge;
5261 infcountmax = consdata->maxactivityneginf
5262 + consdata->maxactivityposinf
5263 + consdata->maxactivityneghuge
5264 + consdata->maxactivityposhuge;
5265
5266 if( infcountmin > 1 && infcountmax > 1 )
5267 return FALSE;
5268
5269 return TRUE;
5270}
5271
5272/** tighten upper bound */
5273static
5275 SCIP* scip, /**< SCIP data structure */
5276 SCIP_CONS* cons, /**< linear constraint */
5277 int pos, /**< variable position */
5278 PROPRULE proprule, /**< propagation rule that deduced the value */
5279 SCIP_Real newub, /**< new upper bound */
5280 SCIP_Real oldub, /**< old upper bound */
5281 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5282 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5283 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5284 )
5285{
5286 SCIP_CONSDATA* consdata;
5287 SCIP_VAR* var;
5288 SCIP_Real lb;
5289 SCIP_Bool infeasible;
5290 SCIP_Bool tightened;
5291
5292 assert(cons != NULL);
5293 assert(!SCIPisInfinity(scip, newub));
5294
5295 consdata = SCIPconsGetData(cons);
5296 assert(consdata != NULL);
5297 var = consdata->vars[pos];
5298 assert(var != NULL);
5299
5300 lb = SCIPvarGetLbLocal(var);
5301 newub = SCIPadjustedVarUb(scip, var, newub);
5302
5303 if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5304 {
5305 SCIP_VARTYPE vartype;
5306
5307 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5308 SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5309 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5310
5311 vartype = SCIPvarGetType(var);
5312
5313 /* tighten upper bound */
5314 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5315
5316 if( infeasible )
5317 {
5318 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5319 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5320
5321 /* analyze conflict */
5323
5324 *cutoff = TRUE;
5325 }
5326 else if( tightened )
5327 {
5328 assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5329 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5330 SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5331
5332 (*nchgbds)++;
5333
5334 /* if variable type was changed we might be able to upgrade the constraint */
5335 if( vartype != SCIPvarGetType(var) )
5336 consdata->upgradetried = FALSE;
5337 }
5338 }
5339 return SCIP_OKAY;
5340}
5341
5342/** tighten lower bound */
5343static
5345 SCIP* scip, /**< SCIP data structure */
5346 SCIP_CONS* cons, /**< linear constraint */
5347 int pos, /**< variable position */
5348 PROPRULE proprule, /**< propagation rule that deduced the value */
5349 SCIP_Real newlb, /**< new lower bound */
5350 SCIP_Real oldlb, /**< old lower bound */
5351 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5352 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5353 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5354 )
5355{
5356 SCIP_CONSDATA* consdata;
5357 SCIP_VAR* var;
5358 SCIP_Real ub;
5359 SCIP_Bool infeasible;
5360 SCIP_Bool tightened;
5361
5362 assert(cons != NULL);
5363 assert(!SCIPisInfinity(scip, newlb));
5364
5365 consdata = SCIPconsGetData(cons);
5366 assert(consdata != NULL);
5367 var = consdata->vars[pos];
5368 assert(var != NULL);
5369
5370 ub = SCIPvarGetUbLocal(var);
5371 newlb = SCIPadjustedVarLb(scip, var, newlb);
5372
5373 if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5374 {
5375 SCIP_VARTYPE vartype;
5376
5377 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5378 SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5379 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5380
5381 vartype = SCIPvarGetType(var);
5382
5383 /* tighten lower bound */
5384 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5385
5386 if( infeasible )
5387 {
5388 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5389 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5390
5391 /* analyze conflict */
5393
5394 *cutoff = TRUE;
5395 }
5396 else if( tightened )
5397 {
5398 assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5399 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5400 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5401
5402 (*nchgbds)++;
5403
5404 /* if variable type was changed we might be able to upgrade the constraint */
5405 if( vartype != SCIPvarGetType(var) )
5406 consdata->upgradetried = FALSE;
5407 }
5408 }
5409 return SCIP_OKAY;
5410}
5411
5412/** tightens bounds of a single variable due to activity bounds (easy case) */
5413static
5415 SCIP* scip, /**< SCIP data structure */
5416 SCIP_CONS* cons, /**< linear constraint */
5417 int pos, /**< position of the variable in the vars array */
5418 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5419 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5420 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5421 )
5422{
5423 SCIP_CONSDATA* consdata;
5424 SCIP_VAR* var;
5425 SCIP_Real val;
5426 SCIP_Real lb;
5427 SCIP_Real ub;
5428 SCIP_Real lhs;
5429 SCIP_Real rhs;
5430
5431 assert(scip != NULL);
5432 assert(cons != NULL);
5433 assert(cutoff != NULL);
5434 assert(nchgbds != NULL);
5435
5436 /* we cannot tighten variables' bounds, if the constraint may be not complete */
5437 if( SCIPconsIsModifiable(cons) )
5438 return SCIP_OKAY;
5439
5440 consdata = SCIPconsGetData(cons);
5441 assert(consdata != NULL);
5442 assert(0 <= pos && pos < consdata->nvars);
5443
5444 *cutoff = FALSE;
5445
5446 var = consdata->vars[pos];
5447 assert(var != NULL);
5448
5449 /* we cannot tighten bounds of multi-aggregated variables */
5451 return SCIP_OKAY;
5452
5453 val = consdata->vals[pos];
5454 lhs = consdata->lhs;
5455 rhs = consdata->rhs;
5456 assert(!SCIPisZero(scip, val));
5457 assert(!SCIPisInfinity(scip, lhs));
5458 assert(!SCIPisInfinity(scip, -rhs));
5459
5460 lb = SCIPvarGetLbLocal(var);
5461 ub = SCIPvarGetUbLocal(var);
5462 assert(SCIPisLE(scip, lb, ub));
5463
5464 /* recompute activities if needed */
5465 if( !consdata->validactivities )
5466 consdataCalcActivities(scip, consdata);
5467 assert(consdata->validactivities);
5468 if( !consdata->validminact )
5470 assert(consdata->validminact);
5471
5472 if( val > 0.0 )
5473 {
5474 /* check, if we can tighten the variable's upper bound */
5475 if( !SCIPisInfinity(scip, rhs) )
5476 {
5477 SCIP_Real slack;
5478 SCIP_Real alpha;
5479
5480 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5481 assert(consdata->validminact);
5482
5483 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5484 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5485 {
5486 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5487 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5488
5489 *cutoff = TRUE;
5490 return SCIP_OKAY;
5491 }
5492
5493 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5494
5495 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5496 * it to zero
5497 */
5498 if( !SCIPisPositive(scip, slack) )
5499 slack = 0.0;
5500
5501 alpha = val * (ub - lb);
5502 assert(!SCIPisNegative(scip, alpha));
5503
5504 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5505 {
5506 SCIP_Real newub;
5507
5508 /* compute new upper bound */
5509 newub = lb + (slack / val);
5510
5511 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5512
5513 if( *cutoff )
5514 {
5515 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5516 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5517
5518 return SCIP_OKAY;
5519 }
5520
5521 /* collect the new upper bound which is needed for the lower bound computation */
5522 ub = SCIPvarGetUbLocal(var);
5523 }
5524 }
5525
5526 /* check, if we can tighten the variable's lower bound */
5527 if( !SCIPisInfinity(scip, -lhs) )
5528 {
5529 SCIP_Real slack;
5530 SCIP_Real alpha;
5531
5532 /* make sure the max activity is reliable */
5533 if( !consdata->validmaxact )
5534 {
5536 }
5537 assert(consdata->validmaxact);
5538
5539 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5540 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5541 {
5542 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5543 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5544
5545 *cutoff = TRUE;
5546 return SCIP_OKAY;
5547 }
5548
5549 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5550
5551 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5552 * it to zero
5553 */
5554 if( !SCIPisPositive(scip, slack) )
5555 slack = 0.0;
5556
5557 alpha = val * (ub - lb);
5558 assert(!SCIPisNegative(scip, alpha));
5559
5560 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5561 {
5562 SCIP_Real newlb;
5563
5564 /* compute new lower bound */
5565 newlb = ub - (slack / val);
5566
5567 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5568
5569 if( *cutoff )
5570 {
5571 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5572 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5573
5574 return SCIP_OKAY;
5575 }
5576 }
5577 }
5578 }
5579 else
5580 {
5581 /* check, if we can tighten the variable's lower bound */
5582 if( !SCIPisInfinity(scip, rhs) )
5583 {
5584 SCIP_Real slack;
5585 SCIP_Real alpha;
5586
5587 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5588 assert(consdata->validminact);
5589
5590 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5591 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5592 {
5593 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5594 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5595
5596 *cutoff = TRUE;
5597 return SCIP_OKAY;
5598 }
5599
5600 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5601
5602 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5603 * it to zero
5604 */
5605 if( !SCIPisPositive(scip, slack) )
5606 slack = 0.0;
5607
5608 alpha = val * (lb - ub);
5609 assert(!SCIPisNegative(scip, alpha));
5610
5611 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5612 {
5613 SCIP_Real newlb;
5614
5615 /* compute new lower bound */
5616 newlb = ub + slack / val;
5617
5618 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5619
5620 if( *cutoff )
5621 {
5622 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5623 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5624
5625 return SCIP_OKAY;
5626 }
5627 /* collect the new lower bound which is needed for the upper bound computation */
5628 lb = SCIPvarGetLbLocal(var);
5629 }
5630 }
5631
5632 /* check, if we can tighten the variable's upper bound */
5633 if( !SCIPisInfinity(scip, -lhs) )
5634 {
5635 SCIP_Real slack;
5636 SCIP_Real alpha;
5637
5638 /* make sure the max activity is reliable */
5639 if( !consdata->validmaxact )
5640 {
5642 }
5643 assert(consdata->validmaxact);
5644
5645 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5646 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5647 {
5648 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5649 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5650
5651 *cutoff = TRUE;
5652 return SCIP_OKAY;
5653 }
5654
5655 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5656
5657 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5658 * it to zero
5659 */
5660 if( !SCIPisPositive(scip, slack) )
5661 slack = 0.0;
5662
5663 alpha = val * (lb - ub);
5664 assert(!SCIPisNegative(scip, alpha));
5665
5666 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5667 {
5668 SCIP_Real newub;
5669
5670 /* compute new upper bound */
5671 newub = lb - (slack / val);
5672
5673 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5674
5675 if( *cutoff )
5676 {
5677 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5678 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5679
5680 return SCIP_OKAY;
5681 }
5682 }
5683 }
5684 }
5685
5686 return SCIP_OKAY;
5687}
5688
5689/** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5690static
5692 SCIP* scip, /**< SCIP data structure */
5693 SCIP_CONS* cons, /**< conflict detecting constraint */
5694 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5695 int nvars, /**< number of variables reasoning the infeasibility */
5696 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5697 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5698 )
5699{
5700#ifndef NDEBUG
5701 SCIP_CONSDATA* consdata;
5702
5703 assert(scip != NULL);
5704 assert(cons != NULL);
5705
5706 consdata = SCIPconsGetData(cons);
5707 assert(consdata != NULL);
5708 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5709#endif
5710
5711 /* conflict analysis can only be applied in solving stage and if it is turned on */
5713 return SCIP_OKAY;
5714
5715 /* initialize conflict analysis */
5717
5718 /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5720
5721 /* add reasoning variables to conflict candidate queue which led to the conflict */
5722 SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5723
5724 /* analyze the conflict */
5726
5727 return SCIP_OKAY;
5728}
5729
5730/** propagate ranged rows
5731 *
5732 * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5733 * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5734 * variables better.
5735 *
5736 * Example:
5737 * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5738 *
5739 * x3 needs to be a multiple of 3, so the instance is infeasible.
5740 *
5741 * Example:
5742 * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5743 *
5744 * The only possible value for x3 is 2, so the variable will be fixed.
5745 *
5746 * @todo add holes if possible
5747 */
5748static
5750 SCIP* scip, /**< SCIP data structure */
5751 SCIP_CONS* cons, /**< linear constraint */
5752 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5753 int* nfixedvars, /**< pointer to count number of fixed variables */
5754 int* nchgbds, /**< pointer to count the number of bound changes */
5755 int* naddconss /**< pointer to count number of added constraints */
5756 )
5757{
5758 SCIP_CONSHDLRDATA* conshdlrdata;
5759 SCIP_CONSHDLR* conshdlr;
5760 SCIP_CONSDATA* consdata;
5761 SCIP_VAR** infcheckvars;
5762 SCIP_Real* infcheckvals;
5763 SCIP_Real minactinfvars;
5764 SCIP_Real maxactinfvars;
5765 SCIP_Real lb;
5766 SCIP_Real ub;
5767 SCIP_Real feastol;
5768 SCIP_Real fixedact;
5769 SCIP_Real lhs;
5770 SCIP_Real rhs;
5771 SCIP_Real absminbincoef;
5772 SCIP_Longint gcd;
5773 SCIP_Longint gcdtmp;
5774 SCIP_Bool minactinfvarsinvalid;
5775 SCIP_Bool maxactinfvarsinvalid;
5776 SCIP_Bool possiblegcd;
5777 SCIP_Bool gcdisone;
5778 SCIP_Bool addartconss;
5779 int ninfcheckvars;
5780 int nunfixedvars;
5781 int nfixedconsvars;
5782 int ncontvars;
5783 int pos;
5784 int v;
5785
5786 assert(scip != NULL);
5787 assert(cons != NULL);
5788 assert(cutoff != NULL);
5789 assert(nfixedvars != NULL);
5790 assert(nchgbds != NULL);
5791 assert(naddconss != NULL);
5792
5793 /* modifiable constraint can be changed so we do not have all necessary information */
5794 if( SCIPconsIsModifiable(cons) )
5795 return SCIP_OKAY;
5796
5797 consdata = SCIPconsGetData(cons);
5798 assert(consdata != NULL);
5799
5800 /* we already did full ranged row propagation */
5801 if( consdata->rangedrowpropagated == 2 )
5802 return SCIP_OKAY;
5803
5804 /* at least three variables are needed */
5805 if( consdata->nvars < 3 )
5806 return SCIP_OKAY;
5807
5808 /* do nothing on normal inequalities */
5809 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5810 return SCIP_OKAY;
5811
5812 /* get constraint handler data */
5813 conshdlr = SCIPconsGetHdlr(cons);
5814 assert(conshdlr != NULL);
5815 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5816 assert(conshdlrdata != NULL);
5817
5818 addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5819
5820 /* we may add artificial constraints */
5821 if( addartconss )
5822 consdata->rangedrowpropagated = 2;
5823 /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5824 * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5825 * artificial constraints
5826 */
5827 else
5828 {
5829 if( consdata->rangedrowpropagated > 0 )
5830 return SCIP_OKAY;
5831
5832 consdata->rangedrowpropagated = 1;
5833 }
5834 fixedact = 0;
5835 nfixedconsvars = 0;
5836 /* calculate fixed activity and number of fixed variables */
5837 for( v = consdata->nvars - 1; v >= 0; --v )
5838 {
5839 /* all zero coefficients should be eliminated */
5840 assert(!SCIPisZero(scip, consdata->vals[v]));
5841
5842 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5843 {
5844 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5845 ++nfixedconsvars;
5846 }
5847 }
5848
5849 /* do not work with huge fixed activities */
5850 if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5851 return SCIP_OKAY;
5852
5853 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5854 assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5855 lhs = consdata->lhs - fixedact;
5856 rhs = consdata->rhs - fixedact;
5857 nunfixedvars = consdata->nvars - nfixedconsvars;
5858
5859 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5860 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5861 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5862
5863 absminbincoef = SCIP_REAL_MAX;
5864 ncontvars = 0;
5865 gcdisone = TRUE;
5866 possiblegcd = TRUE;
5867
5868 /* we now partition all unfixed variables in two groups:
5869 *
5870 * the first one contains all integral variable with integral
5871 * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5872 * given
5873 *
5874 * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5875 * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5876 */
5877
5878 /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5879 * variables
5880 */
5881 ninfcheckvars = 0;
5882 v = -1;
5883 pos = -1;
5884 do
5885 {
5886 ++v;
5887
5888 /* partition the variables, do not change the order of collection, because it might be used later on */
5889 while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5890 !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5891 {
5892 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5893 {
5894 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5895 {
5896 ++ncontvars;
5897 }
5898 else if( SCIPvarIsBinary(consdata->vars[v]) )
5899 {
5900 SCIP_Real absval;
5901
5902 absval = REALABS(consdata->vals[v]);
5903
5904 if( absminbincoef > absval )
5905 absminbincoef = absval;
5906 }
5907
5908 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5909 possiblegcd = FALSE;
5910 infcheckvars[ninfcheckvars] = consdata->vars[v];
5911 infcheckvals[ninfcheckvars] = consdata->vals[v];
5912 ++ninfcheckvars;
5913
5914 if( pos == -1 )
5915 pos = v;
5916 }
5917 ++v;
5918 }
5919 }
5920 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5921
5922 /* if the first group of variables is empty, we stop */
5923 /* @todo try to propagate/split up a constraint of the form:
5924 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5925 * 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]
5926 */
5927 if( v == consdata->nvars )
5928 goto TERMINATE;
5929
5930 /* we need at least two non-continuous variables */
5931 if( ncontvars + 2 > nunfixedvars )
5932 goto TERMINATE;
5933
5934 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5935 assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
5936
5937 feastol = SCIPfeastol(scip);
5938
5939 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5940 assert(gcd >= 2);
5941
5942 /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5943 * calculate gcd over the first part of variables */
5944 for( ; v < consdata->nvars; ++v )
5945 {
5946 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5947 continue;
5948
5949 if( SCIPvarIsBinary(consdata->vars[v]) )
5950 {
5951 SCIP_Real absval;
5952
5953 absval = REALABS(consdata->vals[v]);
5954
5955 if( absminbincoef > absval )
5956 absminbincoef = absval;
5957 }
5958
5959 if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5960 SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5961 {
5962 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5963 ++ncontvars;
5964
5965 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5966 possiblegcd = FALSE;
5967 infcheckvars[ninfcheckvars] = consdata->vars[v];
5968 infcheckvals[ninfcheckvars] = consdata->vals[v];
5969
5970 ++ninfcheckvars;
5971
5972 if( pos == -1 )
5973 pos = v;
5974 }
5975 else
5976 {
5977 assert(REALABS(consdata->vals[v]) > 1.5);
5978
5979 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5980 assert(gcdtmp >= 1);
5981
5982 if( gcdtmp == 1 )
5983 {
5984 infcheckvars[ninfcheckvars] = consdata->vars[v];
5985 infcheckvals[ninfcheckvars] = consdata->vals[v];
5986
5987 ++ninfcheckvars;
5988
5989 if( pos == -1 )
5990 pos = v;
5991 }
5992 else
5993 gcd = gcdtmp;
5994 }
5995 }
5996 assert(gcd >= 2);
5997
5998 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5999 * normalizeCons() */
6000 if( ninfcheckvars == 0 )
6001 goto TERMINATE;
6002
6003 assert(pos >= 0);
6004
6005 minactinfvarsinvalid = FALSE;
6006 maxactinfvarsinvalid = FALSE;
6007 maxactinfvars = 0.0;
6008 minactinfvars = 0.0;
6009
6010 /* calculate activities over all infcheckvars */
6011 for( v = ninfcheckvars - 1; v >= 0; --v )
6012 {
6013 lb = SCIPvarGetLbLocal(infcheckvars[v]);
6014 ub = SCIPvarGetUbLocal(infcheckvars[v]);
6015
6016 if( SCIPisInfinity(scip, -lb) )
6017 {
6018 if( infcheckvals[v] < 0.0 )
6019 maxactinfvarsinvalid = TRUE;
6020 else
6021 minactinfvarsinvalid = TRUE;
6022 }
6023 else
6024 {
6025 if( infcheckvals[v] < 0.0 )
6026 maxactinfvars += infcheckvals[v] * lb;
6027 else
6028 minactinfvars += infcheckvals[v] * lb;
6029 }
6030
6031 if( SCIPisInfinity(scip, ub) )
6032 {
6033 if( infcheckvals[v] > 0.0 )
6034 maxactinfvarsinvalid = TRUE;
6035 else
6036 minactinfvarsinvalid = TRUE;
6037 }
6038 else
6039 {
6040 if( infcheckvals[v] > 0.0 )
6041 maxactinfvars += infcheckvals[v] * ub;
6042 else
6043 minactinfvars += infcheckvals[v] * ub;
6044 }
6045
6046 /* better abort on to big values */
6047 if( SCIPisHugeValue(scip, -minactinfvars) )
6048 minactinfvarsinvalid = TRUE;
6049 if( SCIPisHugeValue(scip, maxactinfvars) )
6050 maxactinfvarsinvalid = TRUE;
6051
6052 if( minactinfvarsinvalid || maxactinfvarsinvalid )
6053 goto TERMINATE;
6054 }
6055 assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6056
6057 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6058 minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6059
6060 /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6061 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6062 * activities */
6063 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6064 * !!!note!!!
6065 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6066 * are not at their global bound
6067 */
6068
6069 /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6070 * infeasibility */
6071 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6072 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6073 {
6074 SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6076
6077 /* start conflict analysis */
6078 /* @todo improve conflict analysis by adding relaxed bounds */
6079 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6080
6081 *cutoff = TRUE;
6082 }
6083 else if( ncontvars == 0 )
6084 {
6085 SCIP_Longint gcdinfvars = -1;
6086
6087 /* check for gcd over all infcheckvars */
6088 if( possiblegcd )
6089 {
6090 v = ninfcheckvars - 1;
6091 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6092 assert(gcdinfvars >= 2);
6093
6094 for( ; v >= 0 && gcdinfvars >= 2; --v )
6095 {
6096 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6097 }
6098 }
6099 else if( gcdisone )
6100 gcdinfvars = 1;
6101
6102 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6103
6104 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6105 if( gcdinfvars >= 1 )
6106 {
6107 SCIP_Real value;
6108 SCIP_Real value2;
6109 SCIP_Real minvalue = SCIP_INVALID;
6110 SCIP_Real maxvalue = SCIP_INVALID;
6111 int nsols = 0;
6112
6113 value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6114
6115 /* check how many possible solutions exist */
6116 while( SCIPisLE(scip, value, maxactinfvars) )
6117 {
6118 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6119
6120 /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6121 if( !SCIPisGE(scip, value2, lhs) )
6122 {
6123 value2 += gcd;
6124 }
6125
6126 if( SCIPisLE(scip, value2, rhs) )
6127 {
6128 ++nsols;
6129
6130 /* early termination if we found more than two solutions */
6131 if( nsols == 3 )
6132 break;
6133
6134 if( minvalue == SCIP_INVALID ) /*lint !e777*/
6135 minvalue = value;
6136
6137 maxvalue = value;
6138 }
6139 value += gcdinfvars;
6140 }
6141 assert(nsols < 2 || minvalue <= maxvalue);
6142
6143 /* determine last possible solution for better bounding */
6144 if( nsols == 3 )
6145 {
6146#ifndef NDEBUG
6147 SCIP_Real secondsolval = maxvalue;
6148#endif
6149 value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6150
6151 /* check how many possible solutions exist */
6152 while( SCIPisGE(scip, value, minactinfvars) )
6153 {
6154 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6155
6156 /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6157 if( !SCIPisLE(scip, value2, rhs) )
6158 {
6159 value2 -= gcd;
6160 }
6161
6162 if( SCIPisGE(scip, value2, lhs) )
6163 {
6164 maxvalue = value;
6165 assert(maxvalue > minvalue);
6166 break;
6167 }
6168 value -= gcdinfvars;
6169 }
6170 assert(maxvalue > secondsolval);
6171 }
6172
6173 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6174 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6175
6176 /* no possible solution found */
6177 if( nsols == 0 )
6178 {
6179 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6180 gcdinfvars, gcd, lhs, rhs);
6181 SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6183
6184 /* start conflict analysis */
6185 /* @todo improve conflict analysis by adding relaxed bounds */
6186 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6187
6188 *cutoff = TRUE;
6189 }
6190 /* if only one solution exist we can extract a new constraint or fix variables */
6191 else if( nsols == 1 )
6192 {
6193 assert(minvalue == maxvalue); /*lint !e777*/
6194
6195 /* we can fix the only variable in our second set of variables */
6196 if( ninfcheckvars == 1 )
6197 {
6198 SCIP_Bool fixed;
6199
6200 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6201
6202 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6203 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6204 SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6205
6206 /* fix variable to only possible value */
6207 SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6208 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6209
6210 if( *cutoff )
6211 {
6212 /* start conflict analysis */
6213 /* @todo improve conflict analysis by adding relaxed bounds */
6214 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6215 }
6216
6217 if( fixed )
6218 ++(*nfixedvars);
6219 }
6220 else
6221 {
6222 /* check for exactly one unfixed variable which is not part of the infcheckvars */
6223 if( ninfcheckvars == nunfixedvars - 1 )
6224 {
6226 SCIP_Bool foundvar = FALSE;
6227 SCIP_Bool fixed;
6228 int w = 0;
6229
6230 assert(ninfcheckvars > 0);
6231
6232 /* find variable which is not an infcheckvar and fix it */
6233 for( v = 0; v < consdata->nvars - 1; ++v )
6234 {
6235 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6236 {
6237 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6238 {
6239#ifndef NDEBUG
6240 int v2 = v + 1;
6241 int w2 = w;
6242
6243 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6244
6245 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6246 {
6247 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6248 continue;
6249
6250 assert(consdata->vars[v2] == infcheckvars[w2]);
6251 ++w2;
6252 }
6253 assert(w2 == ninfcheckvars);
6254#endif
6255 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6256
6257 foundvar = TRUE;
6258
6259 if( consdata->vals[v] < 0 )
6260 {
6261 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6262 }
6263 else
6264 {
6265 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6266 }
6267
6268 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6269 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6270 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6271
6272 /* fix variable to only possible value */
6273 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6274 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6275
6276 if( *cutoff )
6277 {
6278 /* start conflict analysis */
6279 /* @todo improve conflict analysis by adding relaxed bounds */
6280 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6281 consdata->vars[v], bound) );
6282 }
6283
6284 if( fixed )
6285 ++(*nfixedvars);
6286
6287 break;
6288 }
6289
6290 ++w;
6291 }
6292 }
6293
6294 /* maybe last variable was the not infcheckvar */
6295 if( !foundvar )
6296 {
6297 assert(v == consdata->nvars - 1);
6298 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6299
6300 if( consdata->vals[v] < 0 )
6301 {
6302 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6303 }
6304 else
6305 {
6306 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6307 }
6308
6309 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6310 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6311 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6312
6313 /* fix variable to only possible value */
6314 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6315 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6316
6317 if( *cutoff )
6318 {
6319 /* start conflict analysis */
6320 /* @todo improve conflict analysis by adding relaxed bounds */
6321 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6322 consdata->vars[v], bound) );
6323 }
6324
6325 if( fixed )
6326 ++(*nfixedvars);
6327 }
6328 }
6329 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6330 {
6331 /* aggregation possible if we have two variables, but this will be done later on */
6332 SCIP_CONS* newcons;
6333 char name[SCIP_MAXSTRLEN];
6334
6335 /* create, add, and release new artificial constraint */
6336 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6337 ++conshdlrdata->naddconss;
6338
6339 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6340
6341 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6342 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6343 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6344
6345 SCIPdebugPrintCons(scip, newcons, NULL);
6346
6347 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6348
6349 ++(*naddconss);
6350 }
6351 }
6352 }
6353 /* at least two solutions */
6354 else
6355 {
6356 /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6357
6358 /* only one variable in the second set, so we can bound this variables */
6359 if( ninfcheckvars == 1 )
6360 {
6361 SCIP_Bool tightened;
6362 SCIP_Real newlb;
6363 SCIP_Real newub;
6364
6365 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6366
6367 if( infcheckvals[0] < 0 )
6368 {
6369 newlb = maxvalue/infcheckvals[0];
6370 newub = minvalue/infcheckvals[0];
6371 }
6372 else
6373 {
6374 newlb = minvalue/infcheckvals[0];
6375 newub = maxvalue/infcheckvals[0];
6376 }
6377 assert(newlb < newub);
6378
6379 if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6380 {
6381 /* update lower bound of variable */
6382 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6383 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6384
6385 /* tighten variable lower bound to minimal possible value */
6386 SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6387 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6388
6389 if( *cutoff )
6390 {
6391 /* start conflict analysis */
6392 /* @todo improve conflict analysis by adding relaxed bounds */
6393 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6394 }
6395
6396 if( tightened )
6397 ++(*nchgbds);
6398 }
6399
6400 if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6401 {
6402 /* update upper bound of variable */
6403 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6404 SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6405
6406 /* tighten variable upper bound to maximal possible value */
6407 SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6408 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6409
6410 if( *cutoff )
6411 {
6412 /* start conflict analysis */
6413 /* @todo improve conflict analysis by adding relaxed bounds */
6414 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6415 }
6416
6417 if( tightened )
6418 ++(*nchgbds);
6419 }
6420 }
6421 /* check if we have only one not infcheckvars, if so we can tighten this variable */
6422 else if( ninfcheckvars == nunfixedvars - 1 )
6423 {
6424 SCIP_Bool foundvar = FALSE;
6425 SCIP_Bool tightened;
6426 SCIP_Real newlb;
6427 SCIP_Real newub;
6428 int w = 0;
6429
6430 assert(ninfcheckvars > 0);
6431 assert(minvalue < maxvalue);
6432
6433 /* find variable which is not an infcheckvar and fix it */
6434 for( v = 0; v < consdata->nvars - 1; ++v )
6435 {
6436 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6437 {
6438 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6439 {
6440#ifndef NDEBUG
6441 int v2 = v + 1;
6442 int w2 = w;
6443
6444 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6445
6446 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6447 {
6448 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6449 continue;
6450
6451 assert(consdata->vars[v2] == infcheckvars[w2]);
6452 ++w2;
6453 }
6454 assert(w2 == ninfcheckvars);
6455#endif
6456
6457 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6458 foundvar = TRUE;
6459
6460 if( consdata->vals[v] < 0 )
6461 {
6462 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6463 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6464 }
6465 else
6466 {
6467 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6468 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6469 }
6470 assert(SCIPisLE(scip, newlb, newub));
6471
6472 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6473 {
6474 /* update lower bound of variable */
6475 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6476 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6477
6478 /* tighten variable lower bound to minimal possible value */
6479 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6480 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6481
6482 if( *cutoff )
6483 {
6484 /* start conflict analysis */
6485 /* @todo improve conflict analysis by adding relaxed bounds */
6486 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6487 consdata->vars[v], newlb) );
6488 }
6489
6490 if( tightened )
6491 ++(*nchgbds);
6492 }
6493
6494 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6495 {
6496 /* update upper bound of variable */
6497 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6498 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6499
6500 /* tighten variable upper bound to maximal possible value */
6501 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6502 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6503
6504 if( *cutoff )
6505 {
6506 /* start conflict analysis */
6507 /* @todo improve conflict analysis by adding relaxed bounds */
6508 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6509 consdata->vars[v], newub) );
6510 }
6511
6512 if( tightened )
6513 ++(*nchgbds);
6514 }
6515
6516 break;
6517 }
6518
6519 ++w;
6520 }
6521 }
6522
6523 /* maybe last variable was the not infcheckvar */
6524 if( !foundvar )
6525 {
6526 assert(v == consdata->nvars - 1);
6527 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6528
6529 if( consdata->vals[v] < 0 )
6530 {
6531 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6532 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6533 }
6534 else
6535 {
6536 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6537 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6538 }
6539 assert(SCIPisLE(scip, newlb, newub));
6540
6541 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6542 {
6543 /* update lower bound of variable */
6544 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6545 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6546
6547 /* tighten variable lower bound to minimal possible value */
6548 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6549 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6550
6551 if( *cutoff )
6552 {
6553 /* start conflict analysis */
6554 /* @todo improve conflict analysis by adding relaxed bounds */
6555 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6556 }
6557
6558 if( tightened )
6559 ++(*nchgbds);
6560 }
6561
6562 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6563 {
6564 /* update upper bound of variable */
6565 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6566 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6567
6568 /* tighten variable upper bound to maximal possible value */
6569 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6570 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6571
6572 if( *cutoff )
6573 {
6574 /* start conflict analysis */
6575 /* @todo improve conflict analysis by adding relaxed bounds */
6576 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6577 }
6578
6579 if( tightened )
6580 ++(*nchgbds);
6581 }
6582 }
6583 }
6584 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6585 * region for our infcheckvars, if possible
6586 */
6587 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6588 {
6589 SCIP_CONS* newcons;
6590 char name[SCIP_MAXSTRLEN];
6591 SCIP_Real newlhs;
6592 SCIP_Real newrhs;
6593
6594 assert(maxvalue > minvalue);
6595
6596 if( SCIPisGT(scip, minvalue, minactinfvars) )
6597 newlhs = minvalue;
6598 else
6599 newlhs = -SCIPinfinity(scip);
6600
6601 if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6602 newrhs = maxvalue;
6603 else
6604 newrhs = SCIPinfinity(scip);
6605
6606 if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6607 {
6608 /* create, add, and release new artificial constraint */
6609 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6610 ++conshdlrdata->naddconss;
6611
6612 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6613
6614 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6616 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6617
6618 SCIPdebugPrintCons(scip, newcons, NULL);
6619 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6620
6621 ++(*naddconss);
6622 }
6623 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6624 * should be maxvalue */
6625 }
6626 }
6627 }
6628 }
6629 else if( addartconss && ncontvars < ninfcheckvars )
6630 {
6631 SCIP_Real maxact = 0.0;
6632 SCIP_Real minact = 0.0;
6633 int w = 0;
6634
6635 /* compute activities of non-infcheckvars */
6636 for( v = 0; v < consdata->nvars; ++v )
6637 {
6638 if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6639 {
6640 ++w;
6641 continue;
6642 }
6643
6644 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6645 {
6646 if( SCIPvarIsBinary(consdata->vars[v]) )
6647 {
6648 if( consdata->vals[v] > 0.0 )
6649 maxact += consdata->vals[v];
6650 else
6651 minact += consdata->vals[v];
6652 }
6653 else
6654 {
6655 SCIP_Real tmpval;
6656
6657 assert(SCIPvarIsIntegral(consdata->vars[v]));
6658
6659 if( consdata->vals[v] > 0.0 )
6660 {
6661 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6662
6663 if( SCIPisHugeValue(scip, -tmpval) )
6664 break;
6665
6666 minact += tmpval;
6667
6668 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6669
6670 if( SCIPisHugeValue(scip, tmpval) )
6671 break;
6672
6673 maxact += tmpval;
6674 }
6675 else
6676 {
6677 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6678
6679 if( SCIPisHugeValue(scip, -tmpval) )
6680 break;
6681
6682 minact += tmpval;
6683
6684 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6685
6686 if( SCIPisHugeValue(scip, tmpval) )
6687 break;
6688
6689 maxact += tmpval;
6690 }
6691 }
6692 }
6693 }
6694 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6695 {
6696 SCIP_CONS* newcons;
6697 char name[SCIP_MAXSTRLEN];
6698 SCIP_Real newlhs;
6699 SCIP_Real newrhs;
6700
6701 assert(maxact > minact);
6702 assert(w == ninfcheckvars);
6703
6704 newlhs = lhs - maxact;
6705 newrhs = rhs - minact;
6706 assert(newlhs < newrhs);
6707
6708 /* create, add, and release new artificial constraint */
6709 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6710 ++conshdlrdata->naddconss;
6711
6712 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6713
6714 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6716 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6717
6718 SCIPdebugPrintCons(scip, newcons, NULL);
6719 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6720
6721 ++(*naddconss);
6722 }
6723 }
6724
6725 TERMINATE:
6726 SCIPfreeBufferArray(scip, &infcheckvals);
6727 SCIPfreeBufferArray(scip, &infcheckvars);
6728
6729 return SCIP_OKAY;
6730}
6731
6732/** tightens bounds of a single variable due to activity bounds */
6733static
6735 SCIP* scip, /**< SCIP data structure */
6736 SCIP_CONS* cons, /**< linear constraint */
6737 int pos, /**< position of the variable in the vars array */
6738 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6739 int* nchgbds, /**< pointer to count the total number of tightened bounds */
6740 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6741 )
6742{
6743 SCIP_CONSDATA* consdata;
6744 SCIP_VAR* var;
6745 SCIP_Real val;
6746 SCIP_Real lb;
6747 SCIP_Real ub;
6748 SCIP_Real minresactivity;
6749 SCIP_Real maxresactivity;
6750 SCIP_Real lhs;
6751 SCIP_Real rhs;
6752 SCIP_Bool infeasible;
6753 SCIP_Bool tightened;
6754 SCIP_Bool ismintight;
6755 SCIP_Bool ismaxtight;
6756 SCIP_Bool isminsettoinfinity;
6757 SCIP_Bool ismaxsettoinfinity;
6758
6759 assert(scip != NULL);
6760 assert(cons != NULL);
6761 assert(cutoff != NULL);
6762 assert(nchgbds != NULL);
6763
6764 /* we cannot tighten variables' bounds, if the constraint may be not complete */
6765 if( SCIPconsIsModifiable(cons) )
6766 return SCIP_OKAY;
6767
6768 consdata = SCIPconsGetData(cons);
6769 assert(consdata != NULL);
6770 assert(0 <= pos && pos < consdata->nvars);
6771
6772 *cutoff = FALSE;
6773
6774 var = consdata->vars[pos];
6775
6776 /* we cannot tighten bounds of multi-aggregated variables */
6778 return SCIP_OKAY;
6779
6780 val = consdata->vals[pos];
6781 lhs = consdata->lhs;
6782 rhs = consdata->rhs;
6783 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6784 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
6785 assert(var != NULL);
6786 assert(!SCIPisZero(scip, val));
6787 assert(!SCIPisInfinity(scip, lhs));
6788 assert(!SCIPisInfinity(scip, -rhs));
6789
6790 lb = SCIPvarGetLbLocal(var);
6791 ub = SCIPvarGetUbLocal(var);
6792 assert(SCIPisLE(scip, lb, ub));
6793
6794 if( val > 0.0 )
6795 {
6796 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6797 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6798 */
6799 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6800 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6801 {
6802 SCIP_Real newub;
6803
6804 newub = (rhs - minresactivity)/val;
6805
6806 if( !SCIPisInfinity(scip, newub) &&
6807 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6808 {
6809 SCIP_Bool activityunreliable;
6810 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6811
6812 /* check minresactivities for reliability */
6813 if( activityunreliable )
6814 {
6815 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6816 newub = (rhs - minresactivity)/val;
6817 activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6818 (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6819 && (!force || !SCIPisLT(scip, newub, ub)));
6820 }
6821
6822 if( !activityunreliable )
6823 {
6824 /* tighten upper bound */
6825 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6826 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6827 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6828 &infeasible, &tightened) );
6829 if( infeasible )
6830 {
6831 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6832 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6833
6834 /* analyze conflict */
6836
6837 *cutoff = TRUE;
6838 return SCIP_OKAY;
6839 }
6840 if( tightened )
6841 {
6842 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6843 assert(SCIPisFeasLE(scip, ub, newub));
6844 (*nchgbds)++;
6845
6846 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6847 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6848 }
6849 }
6850 }
6851 }
6852
6853 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6854 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6855 {
6856 SCIP_Real newlb;
6857
6858 newlb = (lhs - maxresactivity)/val;
6859 if( !SCIPisInfinity(scip, -newlb) &&
6860 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6861 {
6862 /* check maxresactivities for reliability */
6863 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6864 {
6865 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6866 newlb = (lhs - maxresactivity)/val;
6867
6868 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6869 && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6870 && (!force || !SCIPisGT(scip, newlb, lb))) )
6871 return SCIP_OKAY;
6872 }
6873
6874 /* tighten lower bound */
6875 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6876 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6877 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6878 &infeasible, &tightened) );
6879 if( infeasible )
6880 {
6881 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6882 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6883
6884 /* analyze conflict */
6886
6887 *cutoff = TRUE;
6888 return SCIP_OKAY;
6889 }
6890 if( tightened )
6891 {
6892 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6893 assert(SCIPisFeasGE(scip, lb, newlb));
6894 (*nchgbds)++;
6895 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6896 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6897 }
6898 }
6899 }
6900 }
6901 else
6902 {
6903 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6904 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6905 */
6906 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6907 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6908 {
6909 SCIP_Real newlb;
6910
6911 newlb = (rhs - minresactivity)/val;
6912 if( !SCIPisInfinity(scip, -newlb) &&
6913 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6914 {
6915 SCIP_Bool activityunreliable;
6916 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6917 /* check minresactivities for reliability */
6918 if( activityunreliable )
6919 {
6920 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6921 newlb = (rhs - minresactivity)/val;
6922
6923 activityunreliable = SCIPisInfinity(scip, -minresactivity)
6924 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6925 && (!force || !SCIPisGT(scip, newlb, lb)));
6926 }
6927
6928 if( !activityunreliable )
6929 {
6930 /* tighten lower bound */
6931 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6932 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6933 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6934 &infeasible, &tightened) );
6935 if( infeasible )
6936 {
6937 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6938 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6939
6940 /* analyze conflict */
6942
6943 *cutoff = TRUE;
6944 return SCIP_OKAY;
6945 }
6946 if( tightened )
6947 {
6948 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6949 assert(SCIPisFeasGE(scip, lb, newlb));
6950 (*nchgbds)++;
6951 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6952 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6953 }
6954 }
6955 }
6956 }
6957
6958 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6959 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6960 {
6961 SCIP_Real newub;
6962
6963 newub = (lhs - maxresactivity)/val;
6964 if( !SCIPisInfinity(scip, newub) &&
6965 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6966 {
6967 /* check maxresactivities for reliability */
6968 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6969 {
6970 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6971 newub = (lhs - maxresactivity)/val;
6972
6973 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6974 && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6975 && (!force || !SCIPisLT(scip, newub, ub))) )
6976 return SCIP_OKAY;
6977 }
6978
6979 /* tighten upper bound */
6980 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6981 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6982 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6983 &infeasible, &tightened) );
6984 if( infeasible )
6985 {
6986 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6987 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6988
6989 /* analyze conflict */
6991
6992 *cutoff = TRUE;
6993 return SCIP_OKAY;
6994 }
6995 if( tightened )
6996 {
6997 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6998 assert(SCIPisFeasLE(scip, ub, newub));
6999 (*nchgbds)++;
7000 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7001 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7002 }
7003 }
7004 }
7005 }
7006
7007 return SCIP_OKAY;
7008}
7009
7010#define MAXTIGHTENROUNDS 10
7011
7012/** tightens bounds of variables in constraint due to activity bounds */
7013static
7015 SCIP* scip, /**< SCIP data structure */
7016 SCIP_CONS* cons, /**< linear constraint */
7017 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7018 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7019 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7020 int* nchgbds /**< pointer to count the total number of tightened bounds */
7021 )
7022{
7023 SCIP_CONSDATA* consdata;
7024 unsigned int tightenmode;
7025 int nvars;
7026 int nrounds;
7027 int lastchange;
7028 int oldnchgbds;
7029#ifndef SCIP_DEBUG
7030 int oldnchgbdstotal;
7031#endif
7032 int v;
7033 SCIP_Bool force;
7034 SCIP_Bool easycase;
7035
7036 assert(scip != NULL);
7037 assert(cons != NULL);
7038 assert(nchgbds != NULL);
7039 assert(cutoff != NULL);
7040
7041 *cutoff = FALSE;
7042
7043 /* we cannot tighten variables' bounds, if the constraint may be not complete */
7044 if( SCIPconsIsModifiable(cons) )
7045 return SCIP_OKAY;
7046
7047 /* if a constraint was created after presolve, then it may hold fixed variables
7048 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7049 * thus, ensure here again that variable fixings have been applied
7050 */
7051 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7052 if( *cutoff )
7053 return SCIP_OKAY;
7054
7055 /* check if constraint has any chances of tightening bounds */
7056 if( !canTightenBounds(cons) )
7057 return SCIP_OKAY;
7058
7059 consdata = SCIPconsGetData(cons);
7060 assert(consdata != NULL);
7061
7062 nvars = consdata->nvars;
7063 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7064
7065 /* we are at the root node or during presolving */
7066 if( SCIPgetDepth(scip) < 1 )
7067 tightenmode = 2;
7068 else
7069 tightenmode = 1;
7070
7071 /* stop if we already tightened the constraint and the tightening is not forced */
7072 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7073 return SCIP_OKAY;
7074
7075 /* ensure that the variables are properly sorted */
7076 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7077 {
7078 SCIP_CALL( consdataSort(scip, consdata) );
7079 assert(consdata->coefsorted);
7080 }
7081
7082 /* update maximal activity delta if necessary */
7083 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7085
7086 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7087 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7088 checkMaxActivityDelta(scip, consdata);
7089
7090 /* this may happen if all variables are fixed */
7091 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7092 return SCIP_OKAY;
7093
7094 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7095 {
7096 SCIP_Real slack;
7097 SCIP_Real surplus;
7098 SCIP_Real minactivity;
7099 SCIP_Real maxactivity;
7100 SCIP_Bool ismintight;
7101 SCIP_Bool ismaxtight;
7102 SCIP_Bool isminsettoinfinity;
7103 SCIP_Bool ismaxsettoinfinity;
7104
7105 /* use maximal activity delta to skip propagation (cannot deduce anything) */
7106 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &ismintight, &ismaxtight,
7107 &isminsettoinfinity, &ismaxsettoinfinity);
7108 assert(!SCIPisInfinity(scip, minactivity));
7109 assert(!SCIPisInfinity(scip, -maxactivity));
7110
7111 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7112 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7113
7114 /* check if the constraint will propagate */
7115 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7116 return SCIP_OKAY;
7117 }
7118
7119 /* check if we can use fast implementation for easy and numerically well behaved cases */
7120 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7121
7122 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7123 lastchange = -1;
7124 oldnchgbds = 0;
7125
7126#ifndef SCIP_DEBUG
7127 oldnchgbdstotal = *nchgbds;
7128#endif
7129
7130 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7131 {
7132 /* ensure that the variables are properly sorted
7133 *
7134 * note: it might happen that integer variables become binary during bound tightening at the root node
7135 */
7136 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7137 {
7138 SCIP_CALL( consdataSort(scip, consdata) );
7139 assert(consdata->coefsorted);
7140 }
7141
7142 /* mark the constraint to have the variables' bounds tightened */
7143 consdata->boundstightened = (unsigned int)tightenmode;
7144
7145 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7146 * sorting enables skipping variables
7147 */
7148 v = 0;
7149 while( v < nvars && v != lastchange && !(*cutoff) )
7150 {
7151 oldnchgbds = *nchgbds;
7152
7153 if( easycase )
7154 {
7155 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7156 }
7157 else
7158 {
7159 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7160 }
7161
7162 /* if there was no progress, skip the rest of the binary variables */
7163 if( *nchgbds > oldnchgbds )
7164 {
7165 lastchange = v;
7166 ++v;
7167 }
7168 else if( consdata->coefsorted && v < consdata->nbinvars - 1
7169 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7170 v = consdata->nbinvars;
7171 else
7172 ++v;
7173 }
7174
7175#ifndef SCIP_DEBUG
7176 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7177 *nchgbds - oldnchgbdstotal, nrounds);
7178 oldnchgbdstotal += oldnchgbds;
7179#endif
7180 }
7181
7182#ifndef NDEBUG
7183 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7184 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7185#endif
7186
7187 return SCIP_OKAY;
7188}
7189
7190/** checks linear constraint for feasibility of given solution or current solution */
7191static
7193 SCIP* scip, /**< SCIP data structure */
7194 SCIP_CONS* cons, /**< linear constraint */
7195 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7196 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7197 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7198 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7199 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7200 )
7201{
7202 SCIP_CONSDATA* consdata;
7203 SCIP_Real activity;
7204 SCIP_Real absviol;
7205 SCIP_Real relviol;
7206 SCIP_Real lhsviol;
7207 SCIP_Real rhsviol;
7208
7209 assert(scip != NULL);
7210 assert(cons != NULL);
7211 assert(violated != NULL);
7212
7213 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7215
7216 consdata = SCIPconsGetData(cons);
7217 assert(consdata != NULL);
7218
7219 *violated = FALSE;
7220
7221 if( consdata->row != NULL )
7222 {
7223 if( !checklprows && SCIProwIsInLP(consdata->row) )
7224 return SCIP_OKAY;
7225 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7226 activity = consdataComputePseudoActivity(scip, consdata);
7227 else
7228 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7229 }
7230 else
7231 activity = consdataGetActivity(scip, consdata, sol);
7232
7233 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7234 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7235 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7236 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7237
7238 /* calculate absolute and relative bound violations */
7239 lhsviol = consdata->lhs - activity;
7240 rhsviol = activity - consdata->rhs;
7241
7242 absviol = 0.0;
7243 relviol = 0.0;
7244 if( (lhsviol > 0) && (lhsviol > rhsviol) )
7245 {
7246 absviol = lhsviol;
7247 relviol = SCIPrelDiff(consdata->lhs, activity);
7248 }
7249 else if( rhsviol > 0 )
7250 {
7251 absviol = rhsviol;
7252 relviol = SCIPrelDiff(activity, consdata->rhs);
7253 }
7254
7255 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7256 * return infeasible for safety
7257 */
7258 if( activity == SCIP_INVALID ) /*lint !e777*/
7259 {
7260 assert(sol == NULL);
7261 *violated = TRUE;
7262
7263 /* set violation of invalid pseudo solutions */
7264 absviol = SCIP_INVALID;
7265 relviol = SCIP_INVALID;
7266
7267 /* reset constraint age since we are in enforcement */
7269 }
7270 /* check with relative tolerances (the default) */
7271 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7272 {
7273 /* the "normal" check: one of the two sides is violated */
7274 if( !checkrelmaxabs )
7275 {
7276 *violated = TRUE;
7277
7278 /* only reset constraint age if we are in enforcement */
7279 if( sol == NULL )
7280 {
7282 }
7283 }
7284 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7285 * small compared to the absolute values occurring in the activity
7286 */
7287 else
7288 {
7289 SCIP_Real maxabs;
7290 SCIP_Real coef;
7291 SCIP_Real absval;
7292 SCIP_Real solval;
7293 int v;
7294
7295 maxabs = 1.0;
7296
7297 /* compute maximum absolute value */
7298 for( v = 0; v < consdata->nvars; ++v )
7299 {
7300 if( consdata->vals != NULL )
7301 {
7302 coef = consdata->vals[v];
7303 }
7304 else
7305 coef = 1.0;
7306
7307 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7308 absval = REALABS( coef * solval );
7309 maxabs = MAX( maxabs, absval );
7310 }
7311
7312 /* regard left hand side, first */
7313 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7314 {
7315 /* check whether violation is random noise */
7316 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7317 {
7318 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7319 consdata->lhs - activity, maxabs);
7320 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7321
7322 /* only increase constraint age if we are in enforcement */
7323 if( sol == NULL )
7324 {
7325 SCIP_CALL( SCIPincConsAge(scip, cons) );
7326 }
7327 }
7328 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7329 else if( SCIPisZero(scip, consdata->lhs) )
7330 {
7331 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7332 {
7333 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7334 consdata->lhs - activity, maxabs);
7335 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7336
7337 /* only increase constraint age if we are in enforcement */
7338 if( sol == NULL )
7339 {
7340 SCIP_CALL( SCIPincConsAge(scip, cons) );
7341 }
7342 }
7343 else
7344 {
7345 *violated = TRUE;
7346
7347 /* only reset constraint age if we are in enforcement */
7348 if( sol == NULL )
7349 {
7351 }
7352 }
7353 }
7354 else
7355 {
7356 *violated = TRUE;
7357
7358 /* only reset constraint age if we are in enforcement */
7359 if( sol == NULL )
7360 {
7362 }
7363 }
7364 }
7365
7366 /* now regard right hand side */
7367 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7368 {
7369 /* check whether violation is random noise */
7370 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7371 {
7372 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7373 activity - consdata->rhs, maxabs);
7374 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7375
7376 /* only increase constraint age if we are in enforcement */
7377 if( sol == NULL )
7378 {
7379 SCIP_CALL( SCIPincConsAge(scip, cons) );
7380 }
7381 }
7382 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7383 else if( SCIPisZero(scip, consdata->rhs) )
7384 {
7385 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7386 {
7387 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7388 activity - consdata->rhs, maxabs);
7389 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7390
7391 /* only increase constraint age if we are in enforcement */
7392 if( sol == NULL )
7393 {
7394 SCIP_CALL( SCIPincConsAge(scip, cons) );
7395 }
7396 }
7397 else
7398 {
7399 *violated = TRUE;
7400
7401 /* only reset constraint age if we are in enforcement */
7402 if( sol == NULL )
7403 {
7405 }
7406 }
7407 }
7408 else
7409 {
7410 *violated = TRUE;
7411
7412 /* only reset constraint age if we are in enforcement */
7413 if( sol == NULL )
7414 {
7416 }
7417 }
7418 }
7419 }
7420 }
7421 /* check with absolute tolerances */
7422 else if( consdata->checkabsolute &&
7423 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7424 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7425 {
7426 *violated = TRUE;
7427
7428 /* only reset constraint age if we are in enforcement */
7429 if( sol == NULL )
7430 {
7432 }
7433 }
7434 else
7435 {
7436 /* only increase constraint age if we are in enforcement */
7437 if( sol == NULL )
7438 {
7439 SCIP_CALL( SCIPincConsAge(scip, cons) );
7440 }
7441 }
7442
7443 /* update absolute and relative violation of the solution */
7444 if( sol != NULL )
7445 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7446
7447 return SCIP_OKAY;
7448}
7449
7450/** creates an LP row in a linear constraint data */
7451static
7453 SCIP* scip, /**< SCIP data structure */
7454 SCIP_CONS* cons /**< linear constraint */
7455 )
7456{
7457 SCIP_CONSDATA* consdata;
7458
7459 assert(scip != NULL);
7460 assert(cons != NULL);
7461
7462 consdata = SCIPconsGetData(cons);
7463 assert(consdata != NULL);
7464 assert(consdata->row == NULL);
7465
7466 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7468
7469 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7470
7471 return SCIP_OKAY;
7472}
7473
7474/** adds linear constraint as cut to the LP */
7475static
7477 SCIP* scip, /**< SCIP data structure */
7478 SCIP_CONS* cons, /**< linear constraint */
7479 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7480 )
7481{
7482 SCIP_CONSDATA* consdata;
7483
7484 assert(scip != NULL);
7485 assert(cons != NULL);
7486
7487 consdata = SCIPconsGetData(cons);
7488 assert(consdata != NULL);
7489
7490 if( consdata->row == NULL )
7491 {
7492 if( !SCIPconsIsModifiable(cons) )
7493 {
7494 /* 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
7495 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7496 */
7497 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7498 if( *cutoff )
7499 return SCIP_OKAY;
7500 }
7501
7502 /* convert consdata object into LP row */
7503 SCIP_CALL( createRow(scip, cons) );
7504 }
7505 assert(consdata->row != NULL);
7506
7507 if( consdata->nvars == 0 )
7508 {
7509 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7510 }
7511
7512 /* insert LP row as cut */
7513 if( !SCIProwIsInLP(consdata->row) )
7514 {
7515 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7516 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7517 /* if presolving is turned off, the row might be trivial */
7518 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7519 {
7520 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7521 }
7522#ifndef NDEBUG
7523 else
7524 {
7525 int pr;
7526 int cr;
7527 SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7528 SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7529 assert( pr == 0 || cr == 0 );
7530 }
7531#endif
7532 }
7533
7534 return SCIP_OKAY;
7535}
7536
7537/** adds linear constraint as row to the NLP, if not added yet */
7538static
7540 SCIP* scip, /**< SCIP data structure */
7541 SCIP_CONS* cons /**< linear constraint */
7542 )
7543{
7544 SCIP_CONSDATA* consdata;
7545
7546 assert(SCIPisNLPConstructed(scip));
7547
7548 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7549 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7550 return SCIP_OKAY;
7551
7552 consdata = SCIPconsGetData(cons);
7553 assert(consdata != NULL);
7554
7555 if( consdata->nlrow == NULL )
7556 {
7557 assert(consdata->lhs <= consdata->rhs);
7558
7559 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7560 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7561
7562 assert(consdata->nlrow != NULL);
7563 }
7564
7565 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7566 {
7567 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7568 }
7569
7570 return SCIP_OKAY;
7571}
7572
7573/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7574static
7576 SCIP* scip, /**< SCIP data structure */
7577 SCIP_CONS* cons, /**< linear constraint */
7578 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7579 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7580 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7581 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7582 * the ones with non-zero dual value? */
7583 int* ncuts, /**< pointer to add up the number of found cuts */
7584 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7585 )
7586{
7587 SCIP_CONSDATA* consdata;
7588 SCIP_Bool violated;
7589 int oldncuts;
7590
7591 assert(scip != NULL);
7592 assert(conshdlrdata != NULL);
7593 assert(cons != NULL);
7594 assert(cutoff != NULL);
7595
7596 consdata = SCIPconsGetData(cons);
7597 assert(ncuts != NULL);
7598 assert(consdata != NULL);
7599
7600 oldncuts = *ncuts;
7601 *cutoff = FALSE;
7602
7603 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7604
7605 if( violated )
7606 {
7607 /* insert LP row as cut */
7608 SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7609 (*ncuts)++;
7610 }
7611 else if( !SCIPconsIsModifiable(cons) && separatecards )
7612 {
7613 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7614 if( !separateall && sol == NULL )
7615 {
7616 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7617 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7618 {
7619 SCIP_Real dualsol;
7620
7621 dualsol = SCIProwGetDualsol(consdata->row);
7622 if( SCIPisFeasNegative(scip, dualsol) )
7623 {
7624 if( !SCIPisInfinity(scip, consdata->rhs) )
7625 {
7626 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7627 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7628 }
7629 }
7630 else if( SCIPisFeasPositive(scip, dualsol) )
7631 {
7632 if( !SCIPisInfinity(scip, -consdata->lhs) )
7633 {
7634 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7635 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7636 }
7637 }
7638 }
7639 }
7640 else
7641 {
7642 if( !SCIPisInfinity(scip, consdata->rhs) )
7643 {
7644 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7645 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7646 }
7647 if( !SCIPisInfinity(scip, -consdata->lhs) )
7648 {
7649 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7650 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7651 }
7652 }
7653 }
7654
7655 if( *ncuts > oldncuts )
7656 {
7658 }
7659
7660 return SCIP_OKAY;
7661}
7662
7663/** propagation method for linear constraints */
7664static
7666 SCIP* scip, /**< SCIP data structure */
7667 SCIP_CONS* cons, /**< linear constraint */
7668 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7669 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7670 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7671 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7672 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7673 int* nchgbds /**< pointer to count the total number of tightened bounds */
7674 )
7675{
7676 SCIP_CONSDATA* consdata;
7677 SCIP_Real minactivity;
7678 SCIP_Real maxactivity;
7679 SCIP_Bool isminacttight;
7680 SCIP_Bool ismaxacttight;
7681 SCIP_Bool isminsettoinfinity;
7682 SCIP_Bool ismaxsettoinfinity;
7683
7684 assert(scip != NULL);
7685 assert(cons != NULL);
7686 assert(cutoff != NULL);
7687 assert(nchgbds != NULL);
7688
7689 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7690
7691 consdata = SCIPconsGetData(cons);
7692 assert(consdata != NULL);
7693
7694 if( consdata->eventdata == NULL )
7695 {
7696 SCIP_CONSHDLR* conshdlr;
7697 SCIP_CONSHDLRDATA* conshdlrdata;
7698
7699 conshdlr = SCIPconsGetHdlr(cons);
7700 assert(conshdlr != NULL);
7701
7702 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7703 assert(conshdlrdata != NULL);
7704
7705 /* catch bound change events of variables */
7706 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7707 assert(consdata->eventdata != NULL);
7708 }
7709
7710 *cutoff = FALSE;
7711
7712 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7713 if( !SCIPconsIsModifiable(cons) )
7714 {
7715 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7717 {
7718 SCIP_CALL( SCIPincConsAge(scip, cons) );
7719 }
7720
7721 /* tighten the variable's bounds */
7722 if( tightenbounds )
7723 {
7724 int oldnchgbds;
7725
7726 oldnchgbds = *nchgbds;
7727
7728 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7729
7730 if( *nchgbds > oldnchgbds )
7731 {
7733 }
7734 }
7735
7736 /* propagate ranged rows */
7737 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7738 {
7739 int nfixedvars;
7740 int naddconss;
7741 SCIPdebug( int oldnchgbds = *nchgbds; )
7742
7743 nfixedvars = 0;
7744 naddconss = 0;
7745
7746 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7747
7748 if( *cutoff )
7749 {
7750 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7751 }
7752 else
7753 {
7754 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7755 }
7756
7757 if( nfixedvars > 0 )
7758 *nchgbds += 2*nfixedvars;
7759 } /*lint !e438*/
7760
7761 /* check constraint for infeasibility and redundancy */
7762 if( !(*cutoff) )
7763 {
7764 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
7765 &isminsettoinfinity, &ismaxsettoinfinity);
7766
7767 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7768 {
7769 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7770 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7771
7772 /* analyze conflict */
7774
7776 *cutoff = TRUE;
7777 }
7778 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7779 {
7780 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7781 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7782
7783 /* analyze conflict */
7785
7787 *cutoff = TRUE;
7788 }
7789 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7790 {
7791 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7792 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7793
7794 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7795 if( consdata->nvars > 0 )
7797 else
7798 SCIP_CALL( SCIPdelCons(scip, cons) );
7799 }
7800 }
7801 }
7802
7803 return SCIP_OKAY;
7804}
7805
7806
7807/*
7808 * Presolving methods
7809 */
7810
7811/** converts all variables with fixed domain into FIXED variables */
7812static
7814 SCIP* scip, /**< SCIP data structure */
7815 SCIP_CONS* cons, /**< linear constraint */
7816 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7817 int* nfixedvars /**< pointer to count the total number of fixed variables */
7818 )
7819{
7820 SCIP_CONSDATA* consdata;
7821 SCIP_VAR* var;
7822 SCIP_VARSTATUS varstatus;
7823 SCIP_Real lb;
7824 SCIP_Real ub;
7825 SCIP_Bool fixed;
7826 SCIP_Bool infeasible;
7827 int v;
7828
7829 assert(scip != NULL);
7830 assert(cons != NULL);
7831 assert(cutoff != NULL);
7832 assert(nfixedvars != NULL);
7833
7834 consdata = SCIPconsGetData(cons);
7835 assert(consdata != NULL);
7836
7837 for( v = 0; v < consdata->nvars; ++v )
7838 {
7839 assert(consdata->vars != NULL);
7840 var = consdata->vars[v];
7841 varstatus = SCIPvarGetStatus(var);
7842
7843 if( varstatus != SCIP_VARSTATUS_FIXED )
7844 {
7845 lb = SCIPvarGetLbGlobal(var);
7846 ub = SCIPvarGetUbGlobal(var);
7847 if( SCIPisEQ(scip, lb, ub) )
7848 {
7849 SCIP_Real fixval;
7850
7851 fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7852 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7853 SCIPvarGetName(var), lb, ub, fixval);
7854 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7855 if( infeasible )
7856 {
7857 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7858 *cutoff = TRUE;
7859 return SCIP_OKAY;
7860 }
7861 if( fixed )
7862 (*nfixedvars)++;
7863 }
7864 }
7865 }
7866
7867 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7868
7869 if( infeasible )
7870 {
7871 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7872 *cutoff = TRUE;
7873 return SCIP_OKAY;
7874 }
7875
7876 assert(consdata->removedfixings);
7877
7878 return SCIP_OKAY;
7879}
7880
7881#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7882
7883/** extracts cliques of the constraint and adds them to SCIP
7884 *
7885 * The following clique extraction mechanism are implemeneted
7886 *
7887 * 1. collect binary variables and sort them in non increasing order, then
7888 *
7889 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7890 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7891 * condition
7892 *
7893 * minactivity + vals[i] + vals[i+1] > rhs
7894 *
7895 * and also add the binary to binary implication also for non-successive variables for which the same argument
7896 * holds
7897 *
7898 * minactivity + vals[i] + vals[j] > rhs
7899 *
7900 * 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
7901 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7902 *
7903 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7904 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7905 * condition
7906 *
7907 * maxactivity + vals[i] + vals[i-1] < lhs
7908 *
7909 * and also add the binary to binary implication also for non-successive variables for which the same argument
7910 * holds
7911 *
7912 * maxactivity + vals[i] + vals[j] < lhs
7913 *
7914 * e.g. you could multiply the above example by -1
7915 *
7916 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7917 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7918 * condition
7919 *
7920 * minactivity - vals[i] - vals[i-1] > rhs
7921 *
7922 * and also add the binary to binary implication also for non-successive variables for which the
7923 * same argument holds
7924 *
7925 * minactivity - vals[i] - vals[j] > rhs
7926 *
7927 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7928 * implication x1 = 0 => x3 = 1
7929 *
7930 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7931 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7932 * condition
7933 *
7934 * maxactivity - vals[i] - vals[i+1] < lhs
7935 *
7936 * and also add the binary to binary implication also for non-successive variables for which the same argument
7937 * holds
7938 *
7939 * maxactivity - vals[i] - vals[j] < lhs
7940 *
7941 * e.g. you could multiply the above example by -1
7942 *
7943 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7944 * as clique, (this part is done at the end of the method)
7945 *
7946 */
7947static
7949 SCIP* scip, /**< SCIP data structure */
7950 SCIP_CONS* cons, /**< linear constraint */
7951 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7952 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7953 int* nfixedvars, /**< pointer to count number of fixed variables */
7954 int* nchgbds, /**< pointer to count the total number of tightened bounds */
7955 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7956 )
7957{
7958 SCIP_VAR** vars;
7959 SCIP_Real* vals;
7960 SCIP_CONSDATA* consdata;
7961 SCIP_Bool lhsclique;
7962 SCIP_Bool rhsclique;
7963 SCIP_Bool finitelhs;
7964 SCIP_Bool finiterhs;
7965 SCIP_Bool finiteminact;
7966 SCIP_Bool finitemaxact;
7967 SCIP_Bool finitenegminact;
7968 SCIP_Bool finitenegmaxact;
7969 SCIP_Bool finiteposminact;
7970 SCIP_Bool finiteposmaxact;
7971 SCIP_Bool infeasible;
7972 SCIP_Bool stopped;
7973 int cliquenonzerosadded;
7974 int v;
7975 int i;
7976 int nposcoefs;
7977 int nnegcoefs;
7978 int nvars;
7979
7980 assert(scip != NULL);
7981 assert(cons != NULL);
7982 assert(nfixedvars != NULL);
7983 assert(nchgbds != NULL);
7984 assert(cutoff != NULL);
7985 assert(!SCIPconsIsDeleted(cons));
7986
7987 consdata = SCIPconsGetData(cons);
7988 assert(consdata != NULL);
7989
7990 if( consdata->nvars < 2 )
7991 return SCIP_OKAY;
7992
7993 /* add implications if possible
7994 *
7995 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7996 * maximal absolute contribution and also only if this variable would force all other variables to their bound
7997 * corresponding to the global minimal activity of the constraint
7998 */
7999 if( !consdata->implsadded )
8000 {
8001 /* sort variables by variable type */
8002 SCIP_CALL( consdataSort(scip, consdata) );
8003
8004 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
8005 * up front, might change sorting correspondingly
8006 */
8007 /* fast abort if no binaries seem to exist
8008 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
8009 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
8010 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
8011 * which is the requirement for consdataSort() to actually resort the variables
8012 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
8013 */
8014 if( !SCIPvarIsBinary(consdata->vars[0]) )
8015 return SCIP_OKAY;
8016
8017 nvars = consdata->nvars;
8018 vars = consdata->vars;
8019 vals = consdata->vals;
8020
8021 /* recompute activities if needed */
8022 if( !consdata->validactivities )
8023 consdataCalcActivities(scip, consdata);
8024 assert(consdata->validactivities);
8025
8026 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8027 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8028 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8029 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8030 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8031 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8032 finiteminact = (finitenegminact && finiteposminact);
8033 finitemaxact = (finitenegmaxact && finiteposmaxact);
8034
8035 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8036 {
8037 SCIP_Real maxabscontrib = -1.0;
8038 SCIP_Bool posval = FALSE;
8039 SCIP_Bool allbinary = TRUE;
8040 int oldnchgbds = *nchgbds;
8041 int nbdchgs = 0;
8042 int nimpls = 0;
8043 int position = -1;
8044
8045 /* we need a valid minimal/maximal activity to add cliques */
8046 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8047 {
8049 assert(consdata->validglbminact);
8050 }
8051
8052 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8053 {
8055 assert(consdata->validglbmaxact);
8056 }
8057 assert(consdata->validglbminact || consdata->validglbmaxact);
8058
8059 /* @todo extend this to local/constraint probing */
8060
8061 /* determine maximal contribution to the activity */
8062 for( v = nvars - 1; v >= 0; --v )
8063 {
8064 if( SCIPvarIsBinary(vars[v]) )
8065 {
8066 if( vals[v] > 0 )
8067 {
8068 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8069
8070 if( value > maxabscontrib )
8071 {
8072 maxabscontrib = value;
8073 position = v;
8074 posval = TRUE;
8075 }
8076 }
8077 else
8078 {
8079 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8080
8081 value = REALABS(value);
8082
8083 if( value > maxabscontrib )
8084 {
8085 maxabscontrib = value;
8086 position = v;
8087 posval = FALSE;
8088 }
8089 }
8090 }
8091 else
8092 allbinary = FALSE;
8093 }
8094 assert(0 <= position && position < nvars);
8095
8096 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8097 {
8098 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8099 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8100 * implications
8101 */
8102 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8103 {
8104 for( v = nvars - 1; v >= 0; --v )
8105 {
8106 /* binary to binary implications will be collected when extrating cliques */
8107 if( !SCIPvarIsBinary(vars[v]) )
8108 {
8109 if( v != position )
8110 {
8111 if( vals[v] > 0 )
8112 {
8113 /* add implications */
8114 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8115 ++nimpls;
8116 *nchgbds += nbdchgs;
8117 }
8118 else
8119 {
8120 /* add implications */
8121 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8122 ++nimpls;
8123 *nchgbds += nbdchgs;
8124 }
8125
8126 if( infeasible )
8127 {
8128 *cutoff = TRUE;
8129 break;
8130 }
8131 }
8132 }
8133 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8134 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8135 break;
8136 }
8137 }
8138
8139 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8140 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8141 * implications
8142 */
8143 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8144 {
8145 for( v = nvars - 1; v >= 0; --v )
8146 {
8147 /* binary to binary implications will be collected when extrating cliques */
8148 if( !SCIPvarIsBinary(vars[v]) )
8149 {
8150 if( v != position )
8151 {
8152 if( vals[v] > 0 )
8153 {
8154 /* add implications */
8155 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8156 ++nimpls;
8157 *nchgbds += nbdchgs;
8158 }
8159 else
8160 {
8161 /* add implications */
8162 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8163 ++nimpls;
8164 *nchgbds += nbdchgs;
8165 }
8166
8167 if( infeasible )
8168 {
8169 *cutoff = TRUE;
8170 break;
8171 }
8172 }
8173 }
8174 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8175 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8176 break;
8177 }
8178 }
8179
8180 /* did we find some implications */
8181 if( nimpls > 0 )
8182 {
8183 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8184
8185 if( *cutoff )
8186 return SCIP_OKAY;
8187
8188 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8189 if( *nchgbds - oldnchgbds > 0 )
8190 {
8191 /* check for fixed variables */
8192 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8193 if( *cutoff )
8194 return SCIP_OKAY;
8195
8196 /* tighten variable's bounds */
8197 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8198 if( *cutoff )
8199 return SCIP_OKAY;
8200
8201 /* check for fixed variables */
8202 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8203 if( *cutoff )
8204 return SCIP_OKAY;
8205 }
8206 }
8207 }
8208 }
8209
8210 consdata->implsadded = TRUE;
8211 }
8212
8213 /* check if we already added the cliques of this constraint */
8214 if( consdata->cliquesadded )
8215 return SCIP_OKAY;
8216
8217 consdata->cliquesadded = TRUE;
8218 cliquenonzerosadded = 0;
8219 stopped = FALSE;
8220
8221 /* sort variables by variable type */
8222 SCIP_CALL( consdataSort(scip, consdata) );
8223
8224 nvars = consdata->nvars;
8225 vars = consdata->vars;
8226 vals = consdata->vals;
8227
8228 /**@todo extract more cliques, implications and variable bounds from linear constraints */
8229
8230 /* recompute activities if needed */
8231 if( !consdata->validactivities )
8232 consdataCalcActivities(scip, consdata);
8233 assert(consdata->validactivities);
8234
8235 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8236 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8237 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8238 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8239 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8240 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8241 finiteminact = (finitenegminact && finiteposminact);
8242 finitemaxact = (finitenegmaxact && finiteposmaxact);
8243
8244 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8245 * information
8246 */
8247 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8248 {
8249 SCIP_VAR** binvars;
8250 SCIP_Real* binvarvals;
8251 int nposbinvars = 0;
8252 int nnegbinvars = 0;
8253 int allonebinary = 0;
8254
8255 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8256 SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8257
8258 /* collect binary variables */
8259 for( i = 0; i < nvars; ++i )
8260 {
8261 if( SCIPvarIsBinary(vars[i]) )
8262 {
8263 assert(!SCIPisZero(scip, vals[i]));
8264
8265 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8266 ++allonebinary;
8267
8268 binvars[nposbinvars + nnegbinvars] = vars[i];
8269 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8270
8271 if( SCIPisPositive(scip, vals[i]) )
8272 ++nposbinvars;
8273 else
8274 ++nnegbinvars;
8275
8276 assert(nposbinvars + nnegbinvars <= nvars);
8277 }
8278 /* stop searching for binary variables, because the constraint data is sorted */
8279 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8280 break;
8281 }
8282 assert(nposbinvars + nnegbinvars <= nvars);
8283
8284 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8285 * cliques
8286 */
8287 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8288 {
8289 SCIP_Real threshold;
8290 int oldnchgbds = *nchgbds;
8291 int nbdchgs;
8292 int jstart;
8293 int j;
8294
8295 /* we need a valid minimal/maximal activity to add cliques */
8296 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8297 {
8299 assert(consdata->validglbminact);
8300 }
8301
8302 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8303 {
8305 assert(consdata->validglbmaxact);
8306 }
8307 assert(consdata->validglbminact || consdata->validglbmaxact);
8308
8309 /* sort coefficients non-increasing to be faster in the clique search */
8310 SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8311
8312 /* case a) */
8313 if( finiterhs && finitenegminact && nposbinvars >= 2 )
8314 {
8315 /* compute value that needs to be exceeded */
8316 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8317
8318 j = 1;
8319#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8320 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8321 assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8322#endif
8323 /* check if at least two variables are in a clique */
8324 if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8325 {
8326 ++j;
8327 /* check for extending the clique */
8328 while( j < nposbinvars )
8329 {
8330 if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8331 break;
8332 ++j;
8333 }
8334 assert(j >= 2);
8335
8336 /* add clique with at least two variables */
8337 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8338
8339 if( infeasible )
8340 *cutoff = TRUE;
8341
8342 *nchgbds += nbdchgs;
8343
8344 cliquenonzerosadded += j;
8345 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8346 stopped = TRUE;
8347
8348 /* exchange the last variable in the clique if possible and add all new ones */
8349 if( !stopped && !(*cutoff) && j < nposbinvars )
8350 {
8351 SCIP_VAR** clqvars;
8352 int lastfit = j - 2;
8353 assert(lastfit >= 0);
8354
8355 /* copy all 'main'-clique variables */
8356 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8357
8358 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8359 while( lastfit >= 0 && j < nposbinvars )
8360 {
8361 /* check if two variables are in a clique */
8362 if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8363 {
8364 clqvars[lastfit + 1] = binvars[j];
8365
8366 /* add clique with at least two variables */
8367 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8368
8369 if( infeasible )
8370 {
8371 *cutoff = TRUE;
8372 break;
8373 }
8374
8375 *nchgbds += nbdchgs;
8376
8377 cliquenonzerosadded += (lastfit + 2);
8378 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8379 {
8380 stopped = TRUE;
8381 break;
8382 }
8383
8384 ++j;
8385 }
8386 else
8387 --lastfit;
8388 }
8389
8390 SCIPfreeBufferArray(scip, &clqvars);
8391 }
8392 }
8393 }
8394
8395 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8396 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8397 {
8398 /* check for fixed variables */
8399 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8400
8401 if( !*cutoff )
8402 {
8403 /* tighten variable's bounds */
8404 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8405
8406 if( !*cutoff )
8407 {
8408 /* check for fixed variables */
8409 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8410
8411 if( !*cutoff )
8412 {
8413 /* sort variables by variable type */
8414 SCIP_CALL( consdataSort(scip, consdata) );
8415
8416 /* recompute activities if needed */
8417 if( !consdata->validactivities )
8418 consdataCalcActivities(scip, consdata);
8419 assert(consdata->validactivities);
8420
8421 nvars = consdata->nvars;
8422 vars = consdata->vars;
8423 vals = consdata->vals;
8424 nposbinvars = 0;
8425 nnegbinvars = 0;
8426 allonebinary = 0;
8427
8428 /* update binary variables */
8429 for( i = 0; i < nvars; ++i )
8430 {
8431 if( SCIPvarIsBinary(vars[i]) )
8432 {
8433 assert(!SCIPisZero(scip, vals[i]));
8434
8435 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8436 ++allonebinary;
8437
8438 binvars[nposbinvars + nnegbinvars] = vars[i];
8439 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8440
8441 if( SCIPisPositive(scip, vals[i]) )
8442 ++nposbinvars;
8443 else
8444 ++nnegbinvars;
8445
8446 assert(nposbinvars + nnegbinvars <= nvars);
8447 }
8448 /* stop searching for binary variables, because the constraint data is sorted */
8449 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8450 break;
8451 }
8452 assert(nposbinvars + nnegbinvars <= nvars);
8453 }
8454 }
8455 }
8456
8457 oldnchgbds = *nchgbds;
8458 }
8459
8460 /* case b) */
8461 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8462 {
8463 /* compute value that needs to be deceeded */
8464 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8465
8466 i = nposbinvars + nnegbinvars - 1;
8467 j = i - 1;
8468#ifdef SCIP_DISABLED_CODE
8469 /* assertion should only hold when constraints were fully propagated and boundstightened */
8470 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8471 assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8472#endif
8473 /* check if two variables are in a clique */
8474 if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8475 {
8476 --j;
8477 /* check for extending the clique */
8478 while( j >= nposbinvars )
8479 {
8480 if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8481 break;
8482 --j;
8483 }
8484 jstart = j;
8485
8486 assert(i - j >= 2);
8487 /* add clique with at least two variables */
8488 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8489
8490 if( infeasible )
8491 *cutoff = TRUE;
8492
8493 *nchgbds += nbdchgs;
8494
8495 cliquenonzerosadded += (i - j);
8496 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8497 stopped = TRUE;
8498
8499 /* exchange the last variable in the clique if possible and add all new ones */
8500 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8501 {
8502 SCIP_VAR** clqvars;
8503 int lastfit = jstart + 1;
8504 assert(lastfit < i);
8505
8506 /* copy all 'main'-clique variables */
8507 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8508 ++lastfit;
8509
8510 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8511 while( lastfit <= i && j >= nposbinvars )
8512 {
8513 /* check if two variables are in a clique */
8514 if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8515 {
8516 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8517 clqvars[lastfit - jstart - 2] = binvars[j];
8518
8519 assert(i - lastfit + 2 >= 2);
8520 /* add clique with at least two variables */
8521 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8522
8523 if( infeasible )
8524 {
8525 *cutoff = TRUE;
8526 break;
8527 }
8528
8529 *nchgbds += nbdchgs;
8530
8531 cliquenonzerosadded += (i - lastfit + 2);
8532 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8533 {
8534 stopped = TRUE;
8535 break;
8536 }
8537
8538 --j;
8539 }
8540 else
8541 ++lastfit;
8542 }
8543
8544 SCIPfreeBufferArray(scip, &clqvars);
8545 }
8546 }
8547 }
8548
8549 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8550 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8551 {
8552 /* check for fixed variables */
8553 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8554
8555 if( !*cutoff )
8556 {
8557 /* tighten variable's bounds */
8558 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8559
8560 if( !*cutoff )
8561 {
8562 /* check for fixed variables */
8563 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8564
8565 if( !*cutoff )
8566 {
8567 /* sort variables by variable type */
8568 SCIP_CALL( consdataSort(scip, consdata) );
8569
8570 /* recompute activities if needed */
8571 if( !consdata->validactivities )
8572 consdataCalcActivities(scip, consdata);
8573 assert(consdata->validactivities);
8574
8575 nvars = consdata->nvars;
8576 vars = consdata->vars;
8577 vals = consdata->vals;
8578 nposbinvars = 0;
8579 nnegbinvars = 0;
8580 allonebinary = 0;
8581
8582 /* update binary variables */
8583 for( i = 0; i < nvars; ++i )
8584 {
8585 if( SCIPvarIsBinary(vars[i]) )
8586 {
8587 assert(!SCIPisZero(scip, vals[i]));
8588
8589 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8590 ++allonebinary;
8591
8592 binvars[nposbinvars + nnegbinvars] = vars[i];
8593 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8594
8595 if( SCIPisPositive(scip, vals[i]) )
8596 ++nposbinvars;
8597 else
8598 ++nnegbinvars;
8599
8600 assert(nposbinvars + nnegbinvars <= nvars);
8601 }
8602 /* stop searching for binary variables, because the constraint data is sorted */
8603 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8604 break;
8605 }
8606 assert(nposbinvars + nnegbinvars <= nvars);
8607 }
8608 }
8609 }
8610
8611 oldnchgbds = *nchgbds;
8612 }
8613
8614 /* case c) */
8615 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8616 {
8617 SCIP_Bool* values;
8618
8619 /* initialize clique values array for adding a negated clique */
8620 SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8621 BMSclearMemoryArray(values, nnegbinvars);
8622
8623 /* compute value that needs to be exceeded */
8624 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8625
8626 i = nposbinvars + nnegbinvars - 1;
8627 j = i - 1;
8628
8629#ifdef SCIP_DISABLED_CODE
8630 /* assertion should only hold when constraints were fully propagated and boundstightened */
8631 /* check if the variable should not have already been fixed to one */
8632 assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8633#endif
8634
8635 if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8636 {
8637 --j;
8638 /* check for extending the clique */
8639 while( j >= nposbinvars )
8640 {
8641 if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8642 break;
8643 --j;
8644 }
8645 jstart = j;
8646
8647 assert(i - j >= 2);
8648 /* add negated clique with at least two variables */
8649 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8650
8651 if( infeasible )
8652 *cutoff = TRUE;
8653
8654 *nchgbds += nbdchgs;
8655
8656 cliquenonzerosadded += (i - j);
8657 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8658 stopped = TRUE;
8659
8660 /* exchange the last variable in the clique if possible and add all new ones */
8661 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8662 {
8663 SCIP_VAR** clqvars;
8664 int lastfit = j + 1;
8665 assert(lastfit < i);
8666
8667 /* copy all 'main'-clique variables */
8668 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8669 ++lastfit;
8670
8671 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8672 while( lastfit <= i && j >= nposbinvars )
8673 {
8674 /* check if two variables are in a negated clique */
8675 if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8676 {
8677 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8678 clqvars[lastfit - jstart - 2] = binvars[j];
8679
8680 assert(i - lastfit + 2 >= 2);
8681 /* add clique with at least two variables */
8682 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8683
8684 if( infeasible )
8685 {
8686 *cutoff = TRUE;
8687 break;
8688 }
8689
8690 *nchgbds += nbdchgs;
8691
8692 cliquenonzerosadded += (i - lastfit + 2);
8693 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8694 {
8695 stopped = TRUE;
8696 break;
8697 }
8698
8699 --j;
8700 }
8701 else
8702 ++lastfit;
8703 }
8704
8705 SCIPfreeBufferArray(scip, &clqvars);
8706 }
8707 }
8708
8709 SCIPfreeBufferArray(scip, &values);
8710 }
8711
8712 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8713 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8714 {
8715 /* check for fixed variables */
8716 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8717
8718 if( !*cutoff )
8719 {
8720 /* tighten variable's bounds */
8721 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8722
8723 if( !*cutoff )
8724 {
8725 /* check for fixed variables */
8726 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8727
8728 if( !*cutoff )
8729 {
8730 /* sort variables by variable type */
8731 SCIP_CALL( consdataSort(scip, consdata) );
8732
8733 /* recompute activities if needed */
8734 if( !consdata->validactivities )
8735 consdataCalcActivities(scip, consdata);
8736 assert(consdata->validactivities);
8737
8738 nvars = consdata->nvars;
8739 vars = consdata->vars;
8740 vals = consdata->vals;
8741 nposbinvars = 0;
8742 nnegbinvars = 0;
8743 allonebinary = 0;
8744
8745 /* update binary variables */
8746 for( i = 0; i < nvars; ++i )
8747 {
8748 if( SCIPvarIsBinary(vars[i]) )
8749 {
8750 assert(!SCIPisZero(scip, vals[i]));
8751
8752 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8753 ++allonebinary;
8754
8755 binvars[nposbinvars + nnegbinvars] = vars[i];
8756 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8757
8758 if( SCIPisPositive(scip, vals[i]) )
8759 ++nposbinvars;
8760 else
8761 ++nnegbinvars;
8762
8763 assert(nposbinvars + nnegbinvars <= nvars);
8764 }
8765 /* stop searching for binary variables, because the constraint data is sorted */
8766 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8767 break;
8768 }
8769 assert(nposbinvars + nnegbinvars <= nvars);
8770 }
8771 }
8772 }
8773 }
8774
8775 /* case d) */
8776 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8777 {
8778 SCIP_Bool* values;
8779
8780 /* initialize clique values array for adding a negated clique */
8781 SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8782 BMSclearMemoryArray(values, nposbinvars);
8783
8784 /* compute value that needs to be exceeded */
8785 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8786
8787 j = 1;
8788
8789#ifdef SCIP_DISABLED_CODE
8790 /* assertion should only hold when constraints were fully propagated and boundstightened */
8791 /* check if the variable should not have already been fixed to one */
8792 assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8793#endif
8794
8795 if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8796 {
8797 ++j;
8798 /* check for extending the clique */
8799 while( j < nposbinvars )
8800 {
8801 if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8802 break;
8803 ++j;
8804 }
8805 assert(j >= 2);
8806
8807 /* add negated clique with at least two variables */
8808 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8809
8810 if( infeasible )
8811 *cutoff = TRUE;
8812
8813 *nchgbds += nbdchgs;
8814
8815 cliquenonzerosadded += j;
8816 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8817 stopped = TRUE;
8818
8819 /* exchange the last variable in the clique if possible and add all new ones */
8820 if( !stopped && !(*cutoff) && j < nposbinvars )
8821 {
8822 SCIP_VAR** clqvars;
8823 int lastfit = j - 2;
8824 assert(lastfit >= 0);
8825
8826 /* copy all 'main'-clique variables */
8827 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8828
8829 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8830 while( lastfit >= 0 && j < nposbinvars )
8831 {
8832 /* check if two variables are in a negated clique */
8833 if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8834 {
8835 clqvars[lastfit + 1] = binvars[j];
8836
8837 /* add clique with at least two variables */
8838 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8839
8840 if( infeasible )
8841 {
8842 *cutoff = TRUE;
8843 break;
8844 }
8845
8846 *nchgbds += nbdchgs;
8847
8848 cliquenonzerosadded += lastfit + 2;
8849 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8850 break;
8851
8852 ++j;
8853 }
8854 else
8855 --lastfit;
8856 }
8857
8858 SCIPfreeBufferArray(scip, &clqvars);
8859 }
8860 }
8861
8862 SCIPfreeBufferArray(scip, &values);
8863 }
8864 }
8865
8866 SCIPfreeBufferArray(scip, &binvarvals);
8867 SCIPfreeBufferArray(scip, &binvars);
8868
8869 if( *cutoff )
8870 return SCIP_OKAY;
8871 }
8872
8873 /* 2. we only check if the constraint is a set packing / partitioning constraint */
8874
8875 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8876 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8877 */
8878 nposcoefs = 0;
8879 nnegcoefs = 0;
8880 for( i = 0; i < nvars; ++i )
8881 {
8882 if( !SCIPvarIsBinary(vars[i]) )
8883 return SCIP_OKAY;
8884 else if( SCIPisEQ(scip, vals[i], +1.0) )
8885 nposcoefs++;
8886 else if( SCIPisEQ(scip, vals[i], -1.0) )
8887 nnegcoefs++;
8888 else
8889 return SCIP_OKAY;
8890 }
8891
8892 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8893 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8894
8895 if( lhsclique || rhsclique )
8896 {
8897 SCIP_Bool* values;
8898 int nbdchgs;
8899
8900 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8901 SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8902 SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8903
8904 for( i = 0; i < nvars; ++i )
8905 values[i] = (rhsclique == (vals[i] > 0.0));
8906
8907 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8908
8909 if( infeasible )
8910 *cutoff = TRUE;
8911
8912 *nchgbds += nbdchgs;
8913 SCIPfreeBufferArray(scip, &values);
8914 }
8915
8916 return SCIP_OKAY;
8917}
8918
8919/** tightens left and right hand side of constraint due to integrality */
8920static
8922 SCIP* scip, /**< SCIP data structure */
8923 SCIP_CONS* cons, /**< linear constraint */
8924 int* nchgsides, /**< pointer to count number of side changes */
8925 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8926 )
8927{
8928 SCIP_CONSDATA* consdata;
8929 SCIP_Real newlhs;
8930 SCIP_Real newrhs;
8931 SCIP_Bool chglhs;
8932 SCIP_Bool chgrhs;
8933 SCIP_Bool integral;
8934 int i;
8935
8936 assert(scip != NULL);
8937 assert(cons != NULL);
8938 assert(nchgsides != NULL);
8939 assert(infeasible != NULL);
8940
8941 consdata = SCIPconsGetData(cons);
8942 assert(consdata != NULL);
8943
8944 *infeasible = FALSE;
8945
8946 chglhs = FALSE;
8947 chgrhs = FALSE;
8948 newlhs = -SCIPinfinity(scip);
8949 newrhs = SCIPinfinity(scip);
8950
8951 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8952 {
8953 integral = TRUE;
8954 for( i = 0; i < consdata->nvars && integral; ++i )
8955 {
8956 integral = SCIPisIntegral(scip, consdata->vals[i])
8957 && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
8958 }
8959 if( integral )
8960 {
8961 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8962 {
8963 newlhs = SCIPfeasCeil(scip, consdata->lhs);
8964 chglhs = TRUE;
8965 }
8966 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8967 {
8968 newrhs = SCIPfeasFloor(scip, consdata->rhs);
8969 chgrhs = TRUE;
8970 }
8971
8972 /* check whether rounding would lead to an unsatisfiable constraint */
8973 if( SCIPisGT(scip, newlhs, newrhs) )
8974 {
8975 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
8976 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
8977
8978 *infeasible = TRUE;
8979 return SCIP_OKAY;
8980 }
8981
8982 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8983 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8984
8985 if( chglhs )
8986 {
8987 assert(!SCIPisInfinity(scip, -newlhs));
8988
8989 SCIP_CALL( chgLhs(scip, cons, newlhs) );
8990 if( !consdata->upgraded )
8991 (*nchgsides)++;
8992 }
8993 if( chgrhs )
8994 {
8995 assert(!SCIPisInfinity(scip, newrhs));
8996
8997 SCIP_CALL( chgRhs(scip, cons, newrhs) );
8998 if( !consdata->upgraded )
8999 (*nchgsides)++;
9000 }
9001 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
9002 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9003 }
9004 }
9005
9006 return SCIP_OKAY;
9007}
9008
9009/** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
9010 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
9011 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
9012 * (i) ai >= 0:
9013 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
9014 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
9015 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9016 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9017 * - change coefficients:
9018 * ai' := max(lhs - minact, maxact - rhs, 0)
9019 * lhs' := lhs - (ai - ai')*li
9020 * rhs' := rhs - (ai - ai')*ui
9021 * (ii) ai < 0:
9022 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9023 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9024 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9025 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9026 * - change coefficients:
9027 * ai' := min(rhs - maxact, minact - lhs, 0)
9028 * lhs' := lhs - (ai - ai')*ui
9029 * rhs' := rhs - (ai - ai')*li
9030 *
9031 * We further try to remove variables from the constraint;
9032 * Variables which fulfill conditions (**) or (***) are called relevant variables.
9033 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9034 * variables are set to their "worst" bound. If all variables which are not relevant cannot make the lhs/rhs
9035 * redundant, even if they are set to their "best" bound, they can be removed from the constraint. E.g., for binary
9036 * 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
9037 * inequality, whereas the x_i do not contribute to feasibility and can be removed.
9038 *
9039 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9040 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9041 */
9042static
9044 SCIP* scip, /**< SCIP data structure */
9045 SCIP_CONS* cons, /**< linear constraint */
9046 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9047 int* nchgsides /**< pointer to count number of side changes */
9048 )
9049{
9050 SCIP_CONSDATA* consdata;
9051 SCIP_VAR* var;
9052 SCIP_Bool* isvarrelevant;
9053 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9054 * activity, ignoring the coefficients contributing with infinite value */
9055 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9056 * activity, ignoring the coefficients contributing with infinite value */
9057 SCIP_Bool isminacttight; /* are all contributions to the minactivity non-huge or non-contradicting? */
9058 SCIP_Bool ismaxacttight; /* are all contributions to the maxactivity non-huge or non-contradicting? */
9059 SCIP_Bool isminsettoinfinity;
9060 SCIP_Bool ismaxsettoinfinity;
9061 SCIP_Real minleftactivity; /* minimal activity without relevant variables */
9062 SCIP_Real maxleftactivity; /* maximal activity without relevant variables */
9063 SCIP_Real aggrlhs; /* lhs without minimal activity of relevant variables */
9064 SCIP_Real aggrrhs; /* rhs without maximal activity of relevant variables */
9065 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9066 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9067 SCIP_Real val;
9068 SCIP_Real newval;
9069 SCIP_Real newlhs;
9070 SCIP_Real newrhs;
9071 SCIP_Real lb;
9072 SCIP_Real ub;
9073 int i;
9074
9075 assert(scip != NULL);
9076 assert(cons != NULL);
9077 assert(nchgcoefs != NULL);
9078 assert(nchgsides != NULL);
9079
9080 consdata = SCIPconsGetData(cons);
9081 assert(consdata != NULL);
9082
9083 /* allocate relevance flags */
9084 SCIP_CALL( SCIPallocBufferArray(scip, &isvarrelevant, consdata->nvars) );
9085
9086 /* @todo Is this still needed with automatic recomputation of activities? */
9087 /* if the maximal coefficient is too large, recompute the activities */
9088 if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9089 || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9090 {
9093 }
9094
9095 /* get the minimal and maximal activity of the constraint */
9096 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9097 &isminsettoinfinity, &ismaxsettoinfinity);
9098 assert(( isminsettoinfinity && !SCIPisInfinity(scip, -consdata->lhs) )
9099 || SCIPisLT(scip, minactivity, consdata->lhs)
9100 || ( ismaxsettoinfinity && !SCIPisInfinity(scip, consdata->rhs) )
9101 || SCIPisGT(scip, maxactivity, consdata->rhs));
9102
9103 minleftactivity = 0.0;
9104 maxleftactivity = 0.0;
9105
9106 /* try to tighten each coefficient */
9107 i = 0;
9108 while( i < consdata->nvars )
9109 {
9110 /* get coefficient and variable's bounds */
9111 var = consdata->vars[i];
9112 val = consdata->vals[i];
9113 assert(!SCIPisZero(scip, val));
9114 lb = SCIPvarGetLbLocal(var);
9115 ub = SCIPvarGetUbLocal(var);
9116
9117 /* check sign of coefficient */
9118 if( val >= 0.0 )
9119 {
9120 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9121 isvarrelevant[i] = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS
9122 && SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs);
9123
9124 if( isvarrelevant[i] )
9125 {
9126 /* change coefficients:
9127 * ai' := max(lhs - minact, maxact - rhs)
9128 * lhs' := lhs - (ai - ai')*li
9129 * rhs' := rhs - (ai - ai')*ui
9130 */
9131
9132 lval = consdata->lhs - minactivity;
9133 rval = maxactivity - consdata->rhs;
9134
9135 /* Try to avoid cancellation, if there are only two variables */
9136 if( consdata->nvars == 2 )
9137 {
9138 SCIP_Real otherval;
9139 otherval = consdata->vals[1-i];
9140
9141 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9142 {
9143 lval = consdata->lhs - val*lb;
9144 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9145 }
9146
9147 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9148 {
9149 rval = val*ub - consdata->rhs;
9150 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9151 }
9152 }
9153
9154 newval = MAX3(lval, rval, 0.0);
9155 assert(SCIPisSumRelLE(scip, newval, val));
9156
9157 /* Try to avoid cancellation in computation of lhs/rhs */
9158 newlhs = consdata->lhs - val * lb;
9159 newlhs += newval * lb;
9160 newrhs = consdata->rhs - val * ub;
9161 newrhs += newval * ub;
9162
9163 if( !SCIPisSumRelEQ(scip, newval, val) )
9164 {
9165 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9166 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9167 maxactivity, consdata->lhs, consdata->rhs);
9168
9169 /* update the coefficient and the activity bounds */
9170 if( SCIPisZero(scip, newval) )
9171 {
9172 SCIP_CALL( delCoefPos(scip, cons, i) );
9173 --i;
9174 }
9175 else
9176 {
9177 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9178 }
9179 ++(*nchgcoefs);
9180
9181 /* get the new minimal and maximal activity of the constraint */
9182 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9183 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9184
9185 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9186 {
9187 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9188 consdata->lhs, newlhs);
9189
9190 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9191 (*nchgsides)++;
9192 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9193 }
9194
9195 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9196 {
9197 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9198 consdata->rhs, newrhs);
9199
9200 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9201 (*nchgsides)++;
9202 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9203 }
9204 }
9205 }
9206 else
9207 {
9208 if( !SCIPisInfinity(scip, -minleftactivity) )
9209 {
9210 assert(!SCIPisInfinity(scip, val));
9211 assert(!SCIPisInfinity(scip, lb));
9212 if( SCIPisInfinity(scip, -lb) )
9213 minleftactivity = -SCIPinfinity(scip);
9214 else
9215 minleftactivity += val * lb;
9216 }
9217
9218 if( !SCIPisInfinity(scip, maxleftactivity) )
9219 {
9220 assert(!SCIPisInfinity(scip, val));
9221 assert(!SCIPisInfinity(scip, -ub));
9222 if( SCIPisInfinity(scip,ub) )
9223 maxleftactivity = SCIPinfinity(scip);
9224 else
9225 maxleftactivity += val * ub;
9226 }
9227 }
9228 }
9229 else
9230 {
9231 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9232 isvarrelevant[i] = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS
9233 && SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs);
9234
9235 if( isvarrelevant[i] )
9236 {
9237 /* change coefficients:
9238 * ai' := min(rhs - maxact, minact - lhs)
9239 * lhs' := lhs - (ai - ai')*ui
9240 * rhs' := rhs - (ai - ai')*li
9241 */
9242
9243 lval = minactivity - consdata->lhs;
9244 rval = consdata->rhs - maxactivity;
9245
9246 /* Try to avoid cancellation, if there are only two variables */
9247 if( consdata->nvars == 2 )
9248 {
9249 SCIP_Real otherval;
9250 otherval = consdata->vals[1-i];
9251
9252 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9253 {
9254 lval = val*ub - consdata->lhs;
9255 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9256 }
9257
9258 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9259 {
9260 rval = consdata->rhs - val*lb;
9261 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9262 }
9263 }
9264
9265 newval = MIN3(lval, rval, 0.0);
9266 assert(SCIPisSumRelGE(scip, newval, val));
9267
9268 /* Try to avoid cancellation in computation of lhs/rhs */
9269 newlhs = consdata->lhs - val * ub;
9270 newlhs += newval * ub;
9271 newrhs = consdata->rhs - val * lb;
9272 newrhs += newval * lb;
9273
9274 if( !SCIPisSumRelEQ(scip, newval, val) )
9275 {
9276 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9277 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9278 maxactivity, consdata->lhs, consdata->rhs);
9279
9280 /* update the coefficient and the activity bounds */
9281 if( SCIPisZero(scip, newval) )
9282 {
9283 SCIP_CALL( delCoefPos(scip, cons, i) );
9284 --i;
9285 }
9286 else
9287 {
9288 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9289 }
9290 ++(*nchgcoefs);
9291
9292 /* get the new minimal and maximal activity of the constraint */
9293 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9294 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9295
9296 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9297 {
9298 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9299 consdata->lhs, newlhs);
9300
9301 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9302 (*nchgsides)++;
9303 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9304 }
9305
9306 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9307 {
9308 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9309 consdata->rhs, newrhs);
9310
9311 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9312 (*nchgsides)++;
9313 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9314 }
9315 }
9316 }
9317 else
9318 {
9319 if( !SCIPisInfinity(scip, -minleftactivity) )
9320 {
9321 assert(!SCIPisInfinity(scip, -val));
9322 assert(!SCIPisInfinity(scip, -ub));
9323 if( SCIPisInfinity(scip, ub) )
9324 minleftactivity = -SCIPinfinity(scip);
9325 else
9326 minleftactivity += val * ub;
9327 }
9328
9329 if( !SCIPisInfinity(scip, maxleftactivity) )
9330 {
9331 assert(!SCIPisInfinity(scip, -val));
9332 assert(!SCIPisInfinity(scip, lb));
9333 if( SCIPisInfinity(scip, -lb) )
9334 maxleftactivity = SCIPinfinity(scip);
9335 else
9336 maxleftactivity += val * lb;
9337 }
9338 }
9339 }
9340
9341 ++i;
9342 }
9343
9344 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9345 minleftactivity, consdata->rhs);
9346 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9347 maxleftactivity, consdata->lhs);
9348
9349 /* minleft == \infty ==> minactivity == \infty */
9350 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9351 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9352
9353 /* if the lhs is finite, we will check in the following whether the not relevant variables can make lhs feasible;
9354 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9355 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9356 * (<= the exact minactivity), and we might falsely remove coefficients in the following
9357 */
9358 assert(!SCIPisInfinity(scip, minactivity));
9359 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
9360 goto TERMINATE;
9361
9362 /* if the rhs is finite, we will check in the following whether the not relevant variables can make rhs feasible;
9363 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9364 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9365 * (>= the exact maxactivity), and we might falsely remove coefficients in the following
9366 */
9367 assert(!SCIPisInfinity(scip, -maxactivity));
9368 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
9369 goto TERMINATE;
9370
9371 /* correct lhs and rhs by min/max activity of relevant variables
9372 * relevant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9373 */
9374 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9375 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9376
9377 /* check if the constraint contains variables whose coefficient can be removed. The reasoning is the following:
9378 * Each relevant variable can make the lhs/rhs feasible with a deviation of only one in the bound. If _all_ not
9379 * relevant variables together cannot make lhs/rhs redundant, they can be removed from the constraint. aggrrhs may
9380 * contain some near-infinity value, but only if rhs is infinity.
9381 */
9382 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9383 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9384 {
9385 SCIP_Real minleftactivitypart;
9386 SCIP_Real maxleftactivitypart;
9387
9388 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9389
9390 /* remove redundant variables from constraint */
9391 i = 0;
9392 while( i < consdata->nvars )
9393 {
9394 /* consider redundant variable */
9395 if( !isvarrelevant[i] )
9396 {
9397 /* get coefficient and variable's bounds */
9398 var = consdata->vars[i];
9399 val = consdata->vals[i];
9400 assert(!SCIPisZero(scip, val));
9401 lb = SCIPvarGetLbLocal(var);
9402 ub = SCIPvarGetUbLocal(var);
9403
9404 SCIPdebugMsg(scip, "val = %g\tlhs = %g\trhs = %g\n", val, consdata->lhs, consdata->rhs);
9405 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> from constraint since it is redundant\n",
9406 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
9407
9408 /* check sign of coefficient */
9409 if( val >= 0.0 )
9410 {
9411 minleftactivitypart = val * lb;
9412 maxleftactivitypart = val * ub;
9413 }
9414 else
9415 {
9416 minleftactivitypart = val * ub;
9417 maxleftactivitypart = val * lb;
9418 }
9419
9420 /* remove redundant variable */
9421 isvarrelevant[i] = isvarrelevant[consdata->nvars - 1];
9422 SCIP_CALL( delCoefPos(scip, cons, i) );
9423 --i;
9424
9425 /* adjust lhs and right hand side */
9426 newlhs = consdata->lhs - minleftactivitypart;
9427 newrhs = consdata->rhs - maxleftactivitypart;
9428
9429 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9430 {
9431 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9432 consdata->lhs, newlhs);
9433
9434 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9435 ++(*nchgsides);
9436 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9437 }
9438
9439 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9440 {
9441 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9442 consdata->rhs, newrhs);
9443
9444 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9445 ++(*nchgsides);
9446 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9447 }
9448 }
9449
9450 ++i;
9451 }
9452 }
9453
9454TERMINATE:
9455 /* free relevance flags */
9456 SCIPfreeBufferArray(scip, &isvarrelevant);
9457
9458 return SCIP_OKAY;
9459}
9460
9461/** processes equality with only one variable by fixing the variable and deleting the constraint */
9462static
9464 SCIP* scip, /**< SCIP data structure */
9465 SCIP_CONS* cons, /**< linear constraint */
9466 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9467 int* nfixedvars, /**< pointer to count number of fixed variables */
9468 int* ndelconss /**< pointer to count number of deleted constraints */
9469 )
9470{
9471 SCIP_CONSDATA* consdata;
9472 SCIP_VAR* var;
9473 SCIP_Real val;
9474 SCIP_Real fixval;
9475 SCIP_Bool infeasible;
9476 SCIP_Bool fixed;
9477
9478 assert(scip != NULL);
9479 assert(cons != NULL);
9480 assert(cutoff != NULL);
9481 assert(nfixedvars != NULL);
9482 assert(ndelconss != NULL);
9483
9484 consdata = SCIPconsGetData(cons);
9485 assert(consdata != NULL);
9486 assert(consdata->nvars == 1);
9487 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9488
9489 /* calculate the value to fix the variable to */
9490 var = consdata->vars[0];
9491 val = consdata->vals[0];
9492 assert(!SCIPisZero(scip, val));
9493 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9494 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9495 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9496 SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9497
9498 /* fix variable */
9499 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9500 if( infeasible )
9501 {
9502 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9503 *cutoff = TRUE;
9504 return SCIP_OKAY;
9505 }
9506 if( fixed )
9507 (*nfixedvars)++;
9508
9509 /* disable constraint */
9510 SCIP_CALL( SCIPdelCons(scip, cons) );
9511 if( !consdata->upgraded )
9512 (*ndelconss)++;
9513
9514 return SCIP_OKAY;
9515}
9516
9517/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9518static
9520 SCIP* scip, /**< SCIP data structure */
9521 SCIP_CONS* cons, /**< linear constraint */
9522 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9523 int* naggrvars, /**< pointer to count number of aggregated variables */
9524 int* ndelconss /**< pointer to count number of deleted constraints */
9525 )
9526{
9527 SCIP_CONSDATA* consdata;
9528 SCIP_Bool infeasible;
9529 SCIP_Bool redundant;
9530 SCIP_Bool aggregated;
9531
9532 assert(scip != NULL);
9533 assert(cons != NULL);
9534 assert(cutoff != NULL);
9535 assert(naggrvars != NULL);
9536 assert(ndelconss != NULL);
9537
9538 consdata = SCIPconsGetData(cons);
9539 assert(consdata != NULL);
9540 assert(consdata->nvars == 2);
9541 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9542
9543 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9544 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9545 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9546
9547 /* aggregate the equality */
9548 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9549 consdata->rhs, &infeasible, &redundant, &aggregated) );
9550
9551 /* check for infeasibility of aggregation */
9552 if( infeasible )
9553 {
9554 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9555 *cutoff = TRUE;
9556 return SCIP_OKAY;
9557 }
9558
9559 /* count the aggregation */
9560 if( aggregated )
9561 (*naggrvars)++;
9562
9563 /* delete the constraint, if it is redundant */
9564 if( redundant )
9565 {
9566 SCIP_CALL( SCIPdelCons(scip, cons) );
9567
9568 if( !consdata->upgraded )
9569 (*ndelconss)++;
9570 }
9571
9572 return SCIP_OKAY;
9573}
9574
9575/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9576static
9578 SCIP* scip, /**< SCIP data structure */
9579 SCIP_CONSDATA* consdata, /**< linear constraint data */
9580 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9581 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9582 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9583 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9584 )
9585{
9586 SCIP_Real slackvarlb;
9587 SCIP_Real slackvarub;
9588
9589 assert(scip != NULL);
9590 assert(consdata != NULL);
9591 assert(newlhs != NULL);
9592 assert(newrhs != NULL);
9593 assert(!SCIPisInfinity(scip, -consdata->lhs));
9594 assert(!SCIPisInfinity(scip, consdata->rhs));
9595
9596 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9597 slackvarub = SCIPvarGetUbGlobal(slackvar);
9598 if( slackcoef > 0.0 )
9599 {
9600 if( SCIPisInfinity(scip, -slackvarlb) )
9601 *newrhs = SCIPinfinity(scip);
9602 else
9603 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9604 if( SCIPisInfinity(scip, slackvarub) )
9605 *newlhs = -SCIPinfinity(scip);
9606 else
9607 *newlhs = consdata->lhs - slackcoef * slackvarub;
9608 }
9609 else
9610 {
9611 if( SCIPisInfinity(scip, -slackvarlb) )
9612 *newlhs = -SCIPinfinity(scip);
9613 else
9614 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9615 if( SCIPisInfinity(scip, slackvarub) )
9616 *newrhs = SCIPinfinity(scip);
9617 else
9618 *newrhs = consdata->lhs - slackcoef * slackvarub;
9619 }
9620 assert(SCIPisLE(scip, *newlhs, *newrhs));
9621}
9622
9623/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9624 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9625 * is implicitly integral by this constraint
9626 *
9627 * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9628 * can help.
9629 */
9630static
9632 SCIP* scip, /**< SCIP data structure */
9633 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9634 SCIP_CONS* cons, /**< linear constraint */
9635 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9636 int* naggrvars, /**< pointer to count number of aggregated variables */
9637 int* ndelconss, /**< pointer to count number of deleted constraints */
9638 int* nchgvartypes /**< pointer to count number of changed variable types */
9639 )
9640{
9641 SCIP_CONSDATA* consdata;
9642 SCIP_VAR** vars;
9643 SCIP_Real* vals;
9644 SCIP_VARTYPE bestslacktype;
9645 SCIP_VARTYPE slacktype;
9646 SCIP_Real lhs;
9647 SCIP_Real rhs;
9648 SCIP_Real bestslackdomrng;
9649 SCIP_Real minabsval;
9650 SCIP_Real maxabsval;
9651 SCIP_Bool bestremovescons;
9652 SCIP_Bool coefszeroone;
9653 SCIP_Bool coefsintegral;
9654 SCIP_Bool varsintegral;
9655 SCIP_Bool infeasible;
9656 SCIP_Bool samevar;
9657 int supinf; /* counter for infinite contributions to the supremum of a possible
9658 * multi-aggregation
9659 */
9660 int infinf; /* counter for infinite contributions to the infimum of a possible
9661 * multi-aggregation
9662 */
9663 int maxnlocksstay;
9664 int maxnlocksremove;
9665 int bestslackpos;
9666 int bestnlocks;
9667 int ncontvars;
9668 int contvarpos;
9669 int nintvars;
9670 int nimplvars;
9671 int intvarpos;
9672 int v;
9673
9674 assert(scip != NULL);
9675 assert(cons != NULL);
9676 assert(cutoff != NULL);
9677 assert(naggrvars != NULL);
9678
9679 consdata = SCIPconsGetData(cons);
9680 assert(consdata != NULL);
9681 assert(consdata->nvars > 2);
9682 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9683
9684 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9685
9686 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9687 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9688 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9689 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9690 */
9691 lhs = consdata->lhs;
9692 rhs = consdata->rhs;
9693 maxnlocksstay = 0;
9694 if( consdata->nvars == 3 )
9695 {
9696 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9697 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9698 */
9699 maxnlocksremove = 3;
9700 }
9701 else if( consdata->nvars == 4 )
9702 {
9703 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9704 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9705 */
9706 maxnlocksremove = 2;
9707 }
9708 else
9709 {
9710 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9711 maxnlocksremove = 1;
9712 }
9713
9714 /* the locks on this constraint can be ignored */
9715 if( SCIPconsIsChecked(cons) )
9716 {
9717 if( !SCIPisInfinity(scip, -lhs) )
9718 {
9719 maxnlocksstay++;
9720 maxnlocksremove++;
9721 }
9722 if( !SCIPisInfinity(scip, rhs) )
9723 {
9724 maxnlocksstay++;
9725 maxnlocksremove++;
9726 }
9727 }
9728
9729 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9730 vars = consdata->vars;
9731 vals = consdata->vals;
9732 bestslackpos = -1;
9733 bestslacktype = SCIP_VARTYPE_BINARY;
9734 bestnlocks = INT_MAX;
9735 bestremovescons = FALSE;
9736 bestslackdomrng = 0.0;
9737 coefszeroone = TRUE;
9738 coefsintegral = TRUE;
9739 varsintegral = TRUE;
9740 ncontvars = 0;
9741 contvarpos = -1;
9742 nintvars = 0;
9743 nimplvars = 0;
9744 intvarpos = -1;
9745 minabsval = SCIPinfinity(scip);
9746 maxabsval = -1.0;
9747 for( v = 0; v < consdata->nvars; ++v )
9748 {
9749 SCIP_VAR* var;
9750 SCIP_Real val;
9751 SCIP_Real absval;
9752 SCIP_Real varlb;
9753 SCIP_Real varub;
9754 SCIP_Bool iscont;
9755 int nlocks;
9756
9757 assert(vars != NULL);
9758 assert(vals != NULL);
9759
9760 var = vars[v];
9761 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9763 varlb = SCIPvarGetLbGlobal(var);
9764 varub = SCIPvarGetUbGlobal(var);
9765
9766 val = vals[v];
9767 absval = REALABS(val);
9768 assert(SCIPisPositive(scip, absval));
9769
9770 /* calculate minimal and maximal absolute value */
9771 if( absval < minabsval )
9772 minabsval = absval;
9773 if( absval > maxabsval )
9774 maxabsval = absval;
9775
9776 /*TODO: why exit here when implied integrality can still be derived?!*/
9777 /* do not try to multi aggregate, when numerical bad */
9778 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9779 return SCIP_OKAY;
9780
9781 slacktype = SCIPvarGetType(var);
9782 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9783 coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9784 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9785 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9786
9787 /* update candidates for continuous -> implint and integer -> implint conversion */
9788 if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9789 {
9790 ncontvars++;
9791 contvarpos = v;
9792 }
9793 else if( slacktype == SCIP_VARTYPE_IMPLINT )
9794 {
9795 ++nimplvars;
9796 }
9797 else if( slacktype == SCIP_VARTYPE_INTEGER )
9798 {
9799 nintvars++;
9800 intvarpos = v;
9801 }
9802
9803 /* check, if variable is already fixed or aggregated */
9804 if( !SCIPvarIsActive(var) )
9805 continue;
9806
9807 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9809
9810 if( nlocks > maxnlocksremove )
9811 continue;
9812
9813 /* check, if variable can be used as a slack variable */
9814 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9815 !SCIPdoNotMultaggrVar(scip, var) )
9816 {
9817 SCIP_Bool better;
9818 SCIP_Bool equal;
9819 SCIP_Real slackdomrng;
9820
9821 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9822 slackdomrng = SCIPinfinity(scip);
9823 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9824 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9825 return SCIP_OKAY;
9826 else
9827 {
9828 slackdomrng = (varub - varlb)*absval;
9829 assert(!SCIPisInfinity(scip, slackdomrng));
9830 }
9831 equal = FALSE;
9832 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9833 if( !better && slacktype == bestslacktype )
9834 {
9835 better = (nlocks < bestnlocks);
9836 if( nlocks == bestnlocks && !bestremovescons )
9837 {
9838 better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9839 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9840 }
9841 }
9842
9843 if( better || equal )
9844 {
9845 SCIP_Real minresactivity;
9846 SCIP_Real maxresactivity;
9847 SCIP_Real newlhs;
9848 SCIP_Real newrhs;
9849 SCIP_Bool removescons;
9850 SCIP_Bool ismintight;
9851 SCIP_Bool ismaxtight;
9852 SCIP_Bool isminsettoinfinity;
9853 SCIP_Bool ismaxsettoinfinity;
9854
9855 /* check if the constraint becomes redundant after multi-aggregation */
9856 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9857 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
9858
9859 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9860 * activity
9861 */
9862 if( !ismintight || !ismaxtight )
9863 continue;
9864
9865 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9866 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9867
9868 /* check resactivities for reliability */
9869 if( removescons )
9870 {
9871 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9872 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9873
9874 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9875 && SCIPisFeasLE(scip, newlhs, minresactivity))
9876 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9877
9878 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9879 }
9880
9881 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9882 if( conshdlrdata->multaggrremove && !removescons )
9883 continue;
9884
9885 /* prefer variables that make the constraints redundant */
9886 if( bestremovescons && !removescons )
9887 continue;
9888
9889 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9890 * other constraints
9891 */
9892 if( !removescons && nlocks > maxnlocksstay )
9893 continue;
9894
9895 better = better || (!bestremovescons && removescons);
9896 if( better )
9897 {
9898 bestslackpos = v;
9899 bestslacktype = slacktype;
9900 bestnlocks = nlocks;
9901 bestslackdomrng = slackdomrng;
9902 bestremovescons = removescons;
9903 }
9904 }
9905 }
9906 }
9907
9908 /* if all coefficients and variables are integral, the right hand side must also be integral */
9909 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9910 {
9911 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9913 *cutoff = TRUE;
9914 return SCIP_OKAY;
9915 }
9916
9917 supinf = 0;
9918 infinf = 0;
9919 samevar = FALSE;
9920
9921 /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9922 for( v = 0; v < consdata->nvars; ++v )
9923 {
9924 if( v != bestslackpos )
9925 {
9926 if( SCIPisPositive(scip, consdata->vals[v]) )
9927 {
9928 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9929 {
9930 ++supinf;
9931 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9932 {
9933 ++infinf;
9934 samevar = TRUE;
9935 }
9936 }
9937 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9938 ++infinf;
9939 }
9940 else if( SCIPisNegative(scip, consdata->vals[v]) )
9941 {
9942 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9943 {
9944 ++supinf;
9945 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9946 {
9947 ++infinf;
9948 samevar = TRUE;
9949 }
9950 }
9951 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9952 ++infinf;
9953 }
9954 }
9955 }
9956 assert(!samevar || (supinf > 0 && infinf > 0));
9957
9958 /*TODO: implint detection again terminates early here*/
9959 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9960 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9961 if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9962 {
9963 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9964 return SCIP_OKAY;
9965 }
9966
9967 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9968 * we cannot aggregate the variable, because the integrality condition would get lost
9969 * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9970 * loose the integrality condition for this variable.
9971 */
9972 if( bestslackpos >= 0
9973 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9974 || (coefsintegral && varsintegral && nimplvars == 0)) )
9975 {
9976 SCIP_VAR* slackvar;
9978 SCIP_Real slackcoef;
9979 SCIP_Real aggrconst;
9980 SCIP_Real newlhs;
9981 SCIP_Real newrhs;
9982 SCIP_Bool aggregated;
9983
9984 /* we found a slack variable that only occurs in at most one other constraint:
9985 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9986 */
9987 assert(bestslackpos < consdata->nvars);
9988
9989 /* do not multi aggregate binary variables */
9990 if( SCIPvarIsBinary(vars[bestslackpos]) )
9991 return SCIP_OKAY;
9992
9993 /* convert equality into inequality by deleting the slack variable:
9994 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9995 */
9996 slackvar = vars[bestslackpos];
9997 slackcoef = vals[bestslackpos];
9998 assert(!SCIPisZero(scip, slackcoef));
9999 aggrconst = consdata->rhs/slackcoef;
10000
10001 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
10002 assert(SCIPisLE(scip, newlhs, newrhs));
10003 SCIP_CALL( chgLhs(scip, cons, newlhs) );
10004 SCIP_CALL( chgRhs(scip, cons, newrhs) );
10005 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
10006
10007 /* allocate temporary memory */
10008 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
10009
10010 /* set up the multi-aggregation */
10011 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
10012 for( v = 0; v < consdata->nvars; ++v )
10013 {
10014 scalars[v] = -consdata->vals[v]/slackcoef;
10015 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
10016 }
10017 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
10018 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
10019 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
10020
10021 /* perform the multi-aggregation */
10022 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10023 &infeasible, &aggregated) );
10024 assert(aggregated);
10025
10026 /* free temporary memory */
10028
10029 /* check for infeasible aggregation */
10030 if( infeasible )
10031 {
10032 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10033 *cutoff = TRUE;
10034 return SCIP_OKAY;
10035 }
10036
10037 (*naggrvars)++;
10038
10039 /* delete the constraint if it became redundant */
10040 if( bestremovescons )
10041 {
10042 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10043 SCIP_CALL( SCIPdelCons(scip, cons) );
10044
10045 if( !consdata->upgraded )
10046 (*ndelconss)++;
10047 }
10048 }
10049 else if( ncontvars == 1 )
10050 {
10051 SCIP_VAR* var;
10052
10053 assert(0 <= contvarpos && contvarpos < consdata->nvars);
10054 var = vars[contvarpos];
10056
10057 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10058 {
10059 /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10060 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10061 {
10062 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10063 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10064 SCIPconsGetName(cons), SCIPvarGetName(var));
10065 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10066 (*nchgvartypes)++;
10067 if( infeasible )
10068 {
10069 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10070 *cutoff = TRUE;
10071
10072 return SCIP_OKAY;
10073 }
10074 }
10075 /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10076 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10077 else if( !SCIPdoNotAggr(scip) )
10078 {
10079 SCIP_VAR* newvar;
10080 SCIP_Real absval;
10081 char newvarname[SCIP_MAXSTRLEN];
10082 SCIP_Bool redundant;
10083 SCIP_Bool aggregated;
10084
10085 absval = REALABS(vals[contvarpos]);
10086
10087 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10088
10089 /* create new implicit variable for aggregation */
10090 SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10092
10093 /* add new variable to problem */
10094 SCIP_CALL( SCIPaddVar(scip, newvar) );
10095
10096#ifdef WITH_DEBUG_SOLUTION
10097 if( SCIPdebugIsMainscip(scip) )
10098 {
10099 SCIP_Real varval;
10100 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10101 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10102 }
10103#endif
10104
10105 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10106 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10107 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10108
10109 /* aggregate continuous and implicit variable */
10110 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10111
10112 if( infeasible )
10113 {
10114 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10115 SCIPvarGetName(var), SCIPvarGetName(newvar));
10116 *cutoff = TRUE;
10117
10118 /* release implicit variable */
10119 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10120
10121 return SCIP_OKAY;
10122 }
10123
10124 /* release implicit variable */
10125 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10126
10127 if( aggregated )
10128 (*naggrvars)++;
10129 else
10130 return SCIP_OKAY;
10131 }
10132
10133 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10134 * again
10135 */
10136 consdata->boundstightened = 0;
10137 consdata->rangedrowpropagated = 0;
10138 consdata->presolved = FALSE;
10139 }
10140 }
10141 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10142 {
10143 SCIP_VAR* var;
10144
10145 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10146 * -> we don't convert integers into implints if the row is a 0/1-row
10147 */
10148 assert(varsintegral);
10149 assert(0 <= intvarpos && intvarpos < consdata->nvars);
10150 var = vars[intvarpos];
10151 assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10152
10153 if( coefsintegral
10154 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10155 && SCIPisFeasIntegral(scip, consdata->rhs) )
10156 {
10157 /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10158 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10159 SCIPconsGetName(cons), SCIPvarGetName(var));
10160 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10161 (*nchgvartypes)++;
10162 if( infeasible )
10163 {
10164 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10165 *cutoff = TRUE;
10166
10167 return SCIP_OKAY;
10168 }
10169 }
10170 }
10171
10172 return SCIP_OKAY;
10173}
10174
10175/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10176static
10178 SCIP* scip, /**< SCIP data structure */
10179 SCIP_CONSDATA* consdata, /**< linear constraint data */
10180 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10181 * objective function */
10182 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10183 * this constraint */
10184 )
10185{
10186 SCIP_VAR** vars;
10187 SCIP_VAR* var;
10188 SCIP_Real objval;
10189 SCIP_Bool negated;
10190 int nvars;
10191 int v;
10192
10193 vars = consdata->vars;
10194 nvars = consdata->nvars;
10195
10196 assert(vars != NULL);
10197
10198 for( v = 0; v < nvars; ++v )
10199 {
10200 negated = FALSE;
10201 var = vars[v];
10202 assert(var != NULL);
10203
10204 if( SCIPvarIsNegated(var) )
10205 {
10206 negated = TRUE;
10207 var = SCIPvarGetNegatedVar(var);
10208 assert(var != NULL);
10209 }
10210
10211 objval = SCIPvarGetObj(var);
10212
10213 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10214 * function
10215 */
10216 if( SCIPisZero(scip, objval) )
10217 return FALSE;
10218 else
10219 {
10220 SCIP_Real val;
10221
10222 val = consdata->vals[v];
10223
10224 if( negated )
10225 {
10226 if( v == 0 )
10227 {
10228 /* the first variable defines the scale */
10229 (*scale) = val / -objval;
10230
10231 (*offset) += val;
10232 }
10233 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10234 (*offset) += val;
10235 else
10236 return FALSE;
10237 }
10238 else if( v == 0 )
10239 {
10240 /* the first variable defines the scale */
10241 (*scale) = val / objval;
10242 }
10243 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10244 return FALSE;
10245 }
10246 }
10247
10248 return TRUE;
10249}
10250
10251/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10252 * objective coefficients and add an objective offset
10253 */
10254static
10256 SCIP* scip, /**< SCIP data structure */
10257 SCIP_CONS* cons, /**< linear equation constraint */
10258 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10259 )
10260{
10261 SCIP_CONSDATA* consdata;
10262 SCIP_Real offset;
10263 SCIP_Real scale;
10264 SCIP_Bool applicable;
10265 int nobjvars;
10266 int nvars;
10267 int v;
10268
10269 assert(scip != NULL);
10270 assert(cons != NULL);
10271 assert(conshdlrdata != NULL);
10272
10273 consdata = SCIPconsGetData(cons);
10274 assert(consdata != NULL);
10275 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10276
10277 nvars = consdata->nvars;
10278 nobjvars = SCIPgetNObjVars(scip);
10279
10280 /* check if the linear equality constraints does not have more variables than the objective function */
10281 if( nvars > nobjvars || nvars == 0 )
10282 return SCIP_OKAY;
10283
10284 /* check for allowance of algorithm */
10285 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10286 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10287 return SCIP_OKAY;
10288
10289 offset = consdata->rhs;
10290 scale = 1.0;
10291
10292 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10293 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10294
10295 if( applicable )
10296 {
10297 SCIP_VAR** vars;
10298
10299 vars = consdata->vars;
10300 assert(vars != NULL);
10301
10302 offset /= scale;
10303
10304 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10305 SCIPconsGetName(cons), consdata->rhs, offset);
10306
10307 /* make equality a model constraint to ensure optimality in this direction */
10310
10311 /* set all objective coefficient to zero */
10312 for( v = 0; v < nvars; ++v )
10313 {
10314 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10315 }
10316
10317 /* add an objective offset */
10318 SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10319 }
10320
10321 return SCIP_OKAY;
10322}
10323
10324/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10325static
10327 SCIP* scip, /**< SCIP data structure */
10328 SCIP_CONS* cons, /**< constraint */
10329 SCIP_Real primalbound /**< feasible primal bound */
10330 )
10331{
10332 SCIP_Real cutoffbound;
10333
10334 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10335 * accepted
10336 */
10337 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10338
10339 if( cutoffbound < SCIPgetCutoffbound(scip) )
10340 {
10341 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10342
10343 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10344 }
10345 else
10346 {
10347 SCIP_CONSDATA* consdata;
10348
10349 consdata = SCIPconsGetData(cons);
10350 assert(consdata != NULL);
10351
10352 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10353 * resulted from one side
10354 */
10355 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10356 {
10357 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10358 * propagation
10359 */
10362 }
10363 }
10364
10365 return SCIP_OKAY;
10366}
10367
10368/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10369 * constraint enters the LP by setting the initial and separated flag to FALSE
10370 */
10371static
10373 SCIP* scip, /**< SCIP data structure */
10374 SCIP_CONS* cons, /**< linear constraint */
10375 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10376 )
10377{
10378 SCIP_CONSDATA* consdata;
10379 SCIP_Real offset;
10380 SCIP_Real scale;
10381 SCIP_Bool applicable;
10382 int nobjvars;
10383 int nvars;
10384
10385 assert(scip != NULL);
10386 assert(cons != NULL);
10387 assert(conshdlrdata != NULL);
10388
10389 consdata = SCIPconsGetData(cons);
10390 assert(consdata != NULL);
10391
10392 /* ignore equalities since these are covered by the method checkPartialObjective() */
10393 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10394 return SCIP_OKAY;
10395
10396 nvars = consdata->nvars;
10397 nobjvars = SCIPgetNObjVars(scip);
10398
10399 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10400 * initial and/or separated flag is set to FALSE
10401 */
10402 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10403 return SCIP_OKAY;
10404
10405 offset = 0.0;
10406 scale = 1.0;
10407
10408 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10409 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10410 */
10411 if( nobjvars == 0 )
10412 return SCIP_OKAY;
10413
10414 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10415 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10416
10417 if( applicable )
10418 {
10419 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10420 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10421
10422 assert(scale != 0.0);
10423
10424 if( scale > 0.0 )
10425 {
10426 if( conshdlrdata->detectcutoffbound && rhsfinite )
10427 {
10428 SCIP_Real primalbound;
10429
10430 primalbound = (consdata->rhs - offset) / scale;
10431
10432 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10433 SCIPconsGetName(cons), primalbound);
10434
10435 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10436 }
10437
10438 if( conshdlrdata->detectlowerbound && lhsfinite )
10439 {
10440 SCIP_Real lowerbound;
10441
10442 lowerbound = (consdata->lhs - offset) / scale;
10443
10444 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10445 SCIPconsGetName(cons), lowerbound);
10446
10448 }
10449
10450 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10451 (conshdlrdata->detectlowerbound && !rhsfinite) )
10452 {
10453 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10456 }
10457 }
10458 else
10459 {
10460 if( conshdlrdata->detectlowerbound && rhsfinite )
10461 {
10462 SCIP_Real lowerbound;
10463
10464 lowerbound = (consdata->rhs - offset) / scale;
10465
10466 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10467 SCIPconsGetName(cons), lowerbound);
10468
10470 }
10471
10472 if( conshdlrdata->detectcutoffbound && lhsfinite )
10473 {
10474 SCIP_Real primalbound;
10475
10476 primalbound = (consdata->lhs - offset) / scale;
10477
10478 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10479 SCIPconsGetName(cons), primalbound);
10480
10481 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10482 }
10483
10484 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10485 (conshdlrdata->detectlowerbound && !lhsfinite) )
10486 {
10487 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10490 }
10491 }
10492 }
10493
10494 return SCIP_OKAY;
10495}
10496
10497/** converts special equalities */
10498static
10500 SCIP* scip, /**< SCIP data structure */
10501 SCIP_CONS* cons, /**< linear constraint */
10502 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10503 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10504 int* nfixedvars, /**< pointer to count number of fixed variables */
10505 int* naggrvars, /**< pointer to count number of aggregated variables */
10506 int* ndelconss, /**< pointer to count number of deleted constraints */
10507 int* nchgvartypes /**< pointer to count number of changed variable types */
10508 )
10509{
10510 SCIP_CONSDATA* consdata;
10511
10512 assert(scip != NULL);
10513 assert(cons != NULL);
10514 assert(conshdlrdata != NULL);
10515 assert(cutoff != NULL);
10516 assert(nfixedvars != NULL);
10517 assert(naggrvars != NULL);
10518 assert(ndelconss != NULL);
10519
10520 consdata = SCIPconsGetData(cons);
10521 assert(consdata != NULL);
10522 assert(consdata->removedfixings);
10523
10524 /* do nothing on inequalities */
10525 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10526 return SCIP_OKAY;
10527
10528 /* depending on the number of variables, call a special conversion method */
10529 if( consdata->nvars == 1 )
10530 {
10531 /* fix variable */
10532 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10533 }
10534 else if( consdata->nvars == 2 )
10535 {
10536 /* aggregate one of the variables */
10537 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10538 }
10539 else
10540 {
10541 /* check if the equality is part of the objective function */
10542 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10543
10544 /* try to multi-aggregate one of the variables */
10545 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss, nchgvartypes) );
10546 }
10547
10548 return SCIP_OKAY;
10549}
10550
10551/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10552 * integral
10553 */
10554static
10556 SCIP* scip, /**< SCIP data structure */
10557 SCIP_CONSDATA* consdata, /**< linear constraint */
10558 int pos, /**< position of variable to be left out */
10559 SCIP_Real val /**< value to divide the coefficients by */
10560 )
10561{
10562 int v;
10563
10564 assert(scip != NULL);
10565 assert(consdata != NULL);
10566 assert(0 <= pos && pos < consdata->nvars);
10567
10568 for( v = 0; v < consdata->nvars; ++v )
10569 {
10570 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10571 return FALSE;
10572 }
10573
10574 return TRUE;
10575}
10576
10577/** 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$,
10578 * 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$
10579 */
10580static
10582 SCIP* scip, /**< SCIP data structure */
10583 SCIP_Real side, /**< lhs or rhs */
10584 SCIP_Real val, /**< coefficient */
10585 SCIP_Real minresactivity, /**< minimal residual activity */
10586 SCIP_Real maxresactivity, /**< maximal residual activity */
10587 SCIP_Real* minval, /**< pointer to store calculated minval */
10588 SCIP_Real* maxval /**< pointer to store calculated maxval */
10589 )
10590{
10591 assert(scip != NULL);
10592 assert(minval != NULL);
10593 assert(maxval != NULL);
10594
10595 if( val > 0.0 )
10596 {
10597 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10598 *minval = -maxresactivity;
10599 else
10600 *minval = (side - maxresactivity)/val;
10601
10602 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10603 *maxval = -minresactivity;
10604 else
10605 *maxval = (side - minresactivity)/val;
10606 }
10607 else
10608 {
10609 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10610 *minval = minresactivity;
10611 else
10612 *minval = (side - minresactivity)/val;
10613
10614 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10615 *maxval = maxresactivity;
10616 else
10617 *maxval = (side - maxresactivity)/val;
10618 }
10619}
10620
10621
10622/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10623 * linear inequality
10624 */
10625static
10627 SCIP* scip, /**< SCIP data structure */
10628 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10629 SCIP_CONS* cons, /**< linear constraint */
10630 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10631 int* nfixedvars, /**< pointer to count number of fixed variables */
10632 int* naggrvars, /**< pointer to count number of aggregated variables */
10633 int* ndelconss, /**< pointer to count number of deleted constraints */
10634 int* nchgvartypes /**< pointer to count number of changed variable types */
10635 )
10636{
10637 SCIP_CONSDATA* consdata;
10638 SCIP_Bool lhsexists;
10639 SCIP_Bool rhsexists;
10640 SCIP_Bool bestisint;
10641 SCIP_Bool bestislhs;
10642 SCIP_Real minabsval;
10643 SCIP_Real maxabsval;
10644 int bestpos;
10645 int i;
10646 int maxotherlocks;
10647
10648 assert(scip != NULL);
10649 assert(cons != NULL);
10650 assert(cutoff != NULL);
10651 assert(nfixedvars != NULL);
10652 assert(naggrvars != NULL);
10653 assert(ndelconss != NULL);
10654
10655 /* only process checked constraints (for which the locks are increased);
10656 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10657 * dualfix presolver
10658 */
10659 if( !SCIPconsIsChecked(cons) )
10660 return SCIP_OKAY;
10661
10662 consdata = SCIPconsGetData(cons);
10663 assert(consdata != NULL);
10664
10665 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10666 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10667
10668 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10669 * can use it safely for aggregation and break the search loop
10670 */
10671 bestpos = -1;
10672 bestisint = TRUE;
10673 bestislhs = FALSE;
10674
10675 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10676 * everything else would produce fill-in. Exceptions:
10677 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10678 * produced.
10679 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10680 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10681 * six nonzeros (two variables per substitution).
10682 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10683 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10684 * six nonzeros (three variables per substitution). God exists!
10685 */
10686 if( consdata->nvars <= 2 )
10687 maxotherlocks = INT_MAX;
10688 else if( consdata->nvars == 3 )
10689 maxotherlocks = 3;
10690 else if( consdata->nvars == 4 )
10691 maxotherlocks = 2;
10692 else
10693 maxotherlocks = 1;
10694
10695 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10696 if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10697 maxotherlocks++;
10698
10699 minabsval = SCIPinfinity(scip);
10700 maxabsval = -1.0;
10701 for( i = 0; i < consdata->nvars && bestisint; ++i )
10702 {
10703 SCIP_VAR* var;
10704 SCIP_Bool isint;
10705 SCIP_Real val;
10706 SCIP_Real absval;
10707 SCIP_Real obj;
10708 SCIP_Real lb;
10709 SCIP_Real ub;
10710 SCIP_Bool agglhs;
10711 SCIP_Bool aggrhs;
10712
10713 val = consdata->vals[i];
10714 absval = REALABS(val);
10715
10716 /* calculate minimal and maximal absolute value */
10717 if( absval < minabsval )
10718 minabsval = absval;
10719 if( absval > maxabsval )
10720 maxabsval = absval;
10721
10722 /* do not try to multi aggregate, when numerical bad */
10723 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10724 return SCIP_OKAY;
10725
10726 var = consdata->vars[i];
10728
10729 /* if we already found a candidate, skip integers */
10730 if( bestpos >= 0 && isint )
10731 continue;
10732
10733 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10734 * active, fixed, or single-aggregated with another binary variable
10735 */
10736 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10737 continue;
10738
10739 if ( SCIPdoNotMultaggrVar(scip, var) )
10740 continue;
10741
10742 val = consdata->vals[i];
10743 obj = SCIPvarGetObj(var);
10744 lb = SCIPvarGetLbGlobal(var);
10745 ub = SCIPvarGetUbGlobal(var);
10746
10747 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10748 *
10749 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10750 * - constraint is the only one that forbids fixing the variable to its lower bound
10751 * - 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
10752 *
10753 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10754 * - constraint is the only one that forbids fixing the variable to its upper bound
10755 * - 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
10756 *
10757 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10758 * - constraint is the only one that forbids fixing the variable to its upper bound
10759 * - 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
10760 *
10761 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10762 * - constraint is the only one that forbids fixing the variable to its lower bound
10763 * - 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
10764 *
10765 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10766 * of all x_j
10767 * furthermore: we only want to apply this, if no fill-in will be produced
10768 */
10769 agglhs = lhsexists
10770 && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10771 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10772 || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10773 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10774 aggrhs = rhsexists
10775 && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10776 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10777 || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10778 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10779 if( agglhs || aggrhs )
10780 {
10781 SCIP_Real minresactivity;
10782 SCIP_Real maxresactivity;
10783 SCIP_Real minval;
10784 SCIP_Real maxval;
10785 SCIP_Bool ismintight;
10786 SCIP_Bool ismaxtight;
10787 SCIP_Bool isminsettoinfinity;
10788 SCIP_Bool ismaxsettoinfinity;
10789
10790 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10791 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10792 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
10793 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10794
10795 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10796 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10797 * This is needed, because we do not want to rely on relaxed finite resactivities.
10798 */
10799 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
10800
10801 if( agglhs )
10802 {
10803 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10804 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10805
10806 assert(SCIPisLE(scip, minval, maxval));
10807 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10808 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10809 {
10810 SCIP_Real oldmaxresactivity;
10811 SCIP_Real oldminresactivity;
10812 SCIP_Bool recalculated;
10813
10814 recalculated = FALSE;
10815 oldmaxresactivity = maxresactivity;
10816 oldminresactivity = minresactivity;
10817
10818 /* check minresactivity for reliability */
10819 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10820 {
10821 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10822 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10823 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10824 }
10825
10826 /* check maxresactivity for reliability */
10827 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10828 {
10829 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10830 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10831 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10832 }
10833
10834 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10835 if( recalculated )
10836 {
10837 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10838
10839 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10840 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10841
10842 assert(SCIPisLE(scip, minval, maxval));
10843 }
10844
10845 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10846 {
10847 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10848 * in the multi-aggregation
10849 */
10850 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10851 {
10852 bestpos = i;
10853 bestisint = isint;
10854 bestislhs = TRUE;
10855 continue; /* no need to also look at the right hand side */
10856 }
10857 }
10858 }
10859 }
10860
10861 if( aggrhs )
10862 {
10863 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10864 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10865
10866 assert(SCIPisLE(scip,minval,maxval));
10867 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10868 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10869 {
10870 SCIP_Real oldmaxresactivity;
10871 SCIP_Real oldminresactivity;
10872 SCIP_Bool recalculated;
10873
10874 recalculated = FALSE;
10875 oldmaxresactivity = maxresactivity;
10876 oldminresactivity = minresactivity;
10877
10878 /* check minresactivity for reliability */
10879 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10880 {
10881 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10882 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10883 }
10884
10885 /* check maxresactivity for reliability */
10886 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10887 {
10888 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10889 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10890 }
10891
10892 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10893 if( recalculated )
10894 {
10895 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10896 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10897 assert(SCIPisLE(scip,minval,maxval));
10898 }
10899
10900 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10901 {
10902 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10903 * in the multi-aggregation
10904 */
10905 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10906 {
10907 bestpos = i;
10908 bestisint = isint;
10909 bestislhs = FALSE;
10910 }
10911 }
10912 }
10913 }
10914 }
10915 }
10916
10917 if( bestpos >= 0 )
10918 {
10919 SCIP_VAR** aggrvars;
10920 SCIP_Real* aggrcoefs;
10921 SCIP_Real aggrconst;
10922 SCIP_VAR* bestvar;
10923 SCIP_Real bestval;
10924 SCIP_Real epsilon;
10925 int naggrs;
10926 int j;
10927 SCIP_Bool infeasible;
10928 SCIP_Bool aggregated;
10929 SCIP_Bool samevar;
10930 int supinf; /* counter for infinite contributions to the supremum of a possible
10931 * multi-aggregation
10932 */
10933 int infinf; /* counter for infinite contributions to the infimum of a possible
10934 * multi-aggregation
10935 */
10936
10937 assert(!bestislhs || lhsexists);
10938 assert(bestislhs || rhsexists);
10939
10940 bestvar = consdata->vars[bestpos];
10941 bestval = consdata->vals[bestpos];
10942 assert(bestisint ==
10944
10945 /* allocate temporary memory */
10946 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10947 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10948
10949 /* set up the multi-aggregation */
10951 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10952 naggrs = 0;
10953 supinf = 0;
10954 infinf = 0;
10955 samevar = FALSE;
10956 epsilon = SCIPepsilon(scip);
10957
10958 for( j = 0; j < consdata->nvars; ++j )
10959 {
10960 if( j != bestpos )
10961 {
10962 SCIP_Real absaggrcoef;
10963
10964 aggrvars[naggrs] = consdata->vars[j];
10965 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10966 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10967
10968 absaggrcoef = REALABS(aggrcoefs[naggrs]);
10969
10970 /* do not try to multi aggregate, when numerical bad */
10971 if( absaggrcoef < epsilon )
10972 {
10973 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10974
10975 /* free temporary memory */
10976 SCIPfreeBufferArray(scip, &aggrcoefs);
10977 SCIPfreeBufferArray(scip, &aggrvars);
10978
10979 return SCIP_OKAY;
10980 }
10981
10982 if( bestisint )
10983 {
10984 /* coefficient must be integral: round it to exact integral value */
10985 assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10986 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10987 }
10988
10989 if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10990 {
10991 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10992 {
10993 ++supinf;
10994 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10995 {
10996 ++infinf;
10997 samevar = TRUE;
10998 }
10999 }
11000 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11001 ++infinf;
11002 }
11003 else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
11004 {
11005 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11006 {
11007 ++supinf;
11008 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11009 {
11010 ++infinf;
11011 samevar = TRUE;
11012 }
11013 }
11014 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11015 ++infinf;
11016 }
11017
11018 naggrs++;
11019 }
11020 }
11021 assert(!samevar || (supinf > 0 && infinf > 0));
11022
11023 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11024 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11025 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
11026 assert(naggrs == consdata->nvars-1);
11027
11028 /* right hand side must be integral: round it to exact integral value */
11029 if( bestisint )
11030 {
11031 assert(SCIPisIntegral(scip, aggrconst));
11032 aggrconst = SCIPfloor(scip, aggrconst+0.5);
11033 }
11034
11035 aggregated = FALSE;
11036 infeasible = FALSE;
11037
11038 /* perform the multi-aggregation */
11039 if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11040 {
11041 /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11042 * also convertLongEquality() early termination due to coefficients
11043 */
11044 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11045
11046 /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11047 * the implicitness might rely on the constraint and the integrality of bestvar
11048 */
11049 if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11050 {
11051 SCIP_Bool infeasiblevartypechg;
11052
11053 for( j = 0; j < naggrs; ++j)
11054 {
11055 /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11056 * lead to infeasibility
11057 */
11058 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT )
11059 {
11060 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
11061 (*nchgvartypes)++;
11062 assert(!infeasiblevartypechg);
11063 }
11064 }
11065 }
11066 }
11067 else
11068 {
11069 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11070 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11071 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11072 }
11073 /* free temporary memory */
11074 SCIPfreeBufferArray(scip, &aggrcoefs);
11075 SCIPfreeBufferArray(scip, &aggrvars);
11076
11077 /* check for infeasible aggregation */
11078 if( infeasible )
11079 {
11080 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11081 *cutoff = TRUE;
11082 return SCIP_OKAY;
11083 }
11084
11085 /* delete the constraint, if the aggregation was successful */
11086 if( aggregated )
11087 {
11088 SCIP_CALL( SCIPdelCons(scip, cons) );
11089
11090 if( !consdata->upgraded )
11091 (*ndelconss)++;
11092 (*naggrvars)++;
11093 }
11094 else
11095 {
11096 SCIPdebugMsg(scip, "aggregation non successful!\n");
11097 }
11098 }
11099
11100 return SCIP_OKAY;
11101}
11102
11103#define BINWEIGHT 1
11104#define INTWEIGHT 4
11105#define CONTWEIGHT 8
11106
11107/** gets weight for variable in a "weighted number of variables" sum */
11108static
11110 SCIP_VAR* var /**< variable to get weight for */
11111 )
11112{
11113 switch( SCIPvarGetType(var) )
11114 {
11116 return BINWEIGHT;
11119 return INTWEIGHT;
11121 return CONTWEIGHT;
11122 default:
11123 SCIPerrorMessage("invalid variable type\n");
11124 SCIPABORT();
11125 return 0; /*lint !e527*/
11126 }
11127}
11128
11129/** tries to aggregate variables in equations a^Tx = lhs
11130 * in case there are at most two binary variables with an odd coefficient and all other
11131 * variables are not continuous and have an even coefficient then:
11132 * - exactly one odd binary variables
11133 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11134 * - lhs is odd -> y = 1
11135 * - lhs is even -> y = 0
11136 * - exactly two odd binary variables
11137 * aggregate the two binary variables with odd coefficient
11138 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11139 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11140 */
11141static
11143 SCIP* scip, /**< SCIP data structure */
11144 SCIP_CONS* cons, /**< linear constraint */
11145 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11146 int* nfixedvars, /**< pointer to count number of fixed variables */
11147 int* naggrvars /**< pointer to count number of aggregated variables */
11148 )
11149{ /*lint --e{715}*/
11150 SCIP_CONSDATA* consdata;
11151 SCIP_Bool success;
11152
11153 assert( scip != NULL );
11154 assert( cons != NULL );
11155
11156 consdata = SCIPconsGetData(cons);
11157 assert( consdata != NULL );
11158
11159 /* check if the linear constraint is an equation with integral right hand side */
11160 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11161 return SCIP_OKAY;
11162
11163 /* try to fix and aggregated variables until nothing is possible anymore */
11164 do
11165 {
11166 int v;
11167 int nvars;
11168 SCIP_VAR** vars;
11169 SCIP_Real* vals;
11170 SCIP_Real lhs;
11171 SCIP_Bool lhsodd;
11172
11173 SCIP_Bool infeasible;
11174 SCIP_Bool fixed;
11175 SCIP_Bool aggregated;
11176 SCIP_Bool redundant;
11177
11178 SCIP_VAR* var1;
11179 SCIP_VAR* var2;
11180 int noddvars;
11181
11182 success = FALSE;
11183
11184 lhs = consdata->lhs;
11185 vars = consdata->vars;
11186 vals = consdata->vals;
11187 nvars = consdata->nvars;
11188
11189 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11190
11191 var1 = NULL;
11192 var2 = NULL;
11193 noddvars = 0;
11194
11195 /* search for binary variables with an odd coefficient */
11196 for( v = 0; v < nvars && noddvars < 3; ++v )
11197 {
11198 SCIP_Longint val;
11199
11200 /* all coefficients and variables have to be integral */
11201 if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11202 return SCIP_OKAY;
11203
11204 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11205 if( val % 2 != 0 )
11206 {
11207 /* the odd values have to belong to binary variables */
11208 if( !SCIPvarIsBinary(vars[v]) )
11209 return SCIP_OKAY;
11210
11211 if( noddvars == 0 )
11212 var1 = vars[v];
11213 else
11214 var2 = vars[v];
11215
11216 noddvars++;
11217 }
11218 }
11219
11220 /* check lhs is odd or even */
11221 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11222
11223 if( noddvars == 1 )
11224 {
11225 assert( var1 != NULL );
11226
11227 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11228 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11229
11230 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11231
11232 /* check for infeasibility of fixing */
11233 if( infeasible )
11234 {
11235 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11236 *cutoff = TRUE;
11237 return SCIP_OKAY;
11238 }
11239
11240 if( fixed )
11241 {
11242 SCIPdebugMsg(scip, " -> feasible fixing\n");
11243 (*nfixedvars)++;
11244 success = TRUE;
11245 }
11246 }
11247 else if( noddvars == 2 )
11248 {
11249 assert( var1 != NULL );
11250 assert( var2 != NULL );
11251
11252 /* aggregate the two variables with odd coefficient
11253 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11254 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11255 */
11256 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11257 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11258
11259 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11260 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11261
11262 /* check for infeasibility of aggregation */
11263 if( infeasible )
11264 {
11265 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11266 *cutoff = TRUE;
11267 return SCIP_OKAY;
11268 }
11269
11270 /* count the aggregation */
11271 if( aggregated )
11272 {
11273 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11274 (*naggrvars)++;
11275 success = TRUE;
11276 }
11277 }
11278
11279 if( success )
11280 {
11281 /* apply fixings and aggregation to successfully rerun this presolving step */
11282 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11283
11284 if( infeasible )
11285 {
11286 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11287 *cutoff = TRUE;
11288 return SCIP_OKAY;
11289 }
11290
11291 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11292
11293 if( infeasible )
11294 {
11295 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11296 *cutoff = TRUE;
11297 return SCIP_OKAY;
11298 }
11299 }
11300 }
11301 while( success && consdata->nvars >= 1 );
11302
11303 return SCIP_OKAY;
11304}
11305
11306
11307
11308/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11309 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11310 * coefficients
11311 */
11312static
11314{ /*lint --e{715}*/
11315 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11316 SCIP_VARTYPE vartype1;
11317 SCIP_VARTYPE vartype2;
11318 SCIP_Real value;
11319
11320 assert(consdata != NULL);
11321 assert(0 <= ind1 && ind1 < consdata->nvars);
11322 assert(0 <= ind2 && ind2 < consdata->nvars);
11323
11324 vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11325 vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11326
11327 if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11328 {
11329 /* continuous varibles will be sorted to the back */
11330 if( vartype2 != vartype1 )
11331 return +1;
11332 /* both variables are continuous */
11333 else
11334 return 0;
11335 }
11336 /* continuous variables will be sorted to the back */
11337 else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11338 return -1;
11339
11340 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11341
11342 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11343 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11344}
11345
11346/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11347 *
11348 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11349 * then we can change this constraint to 1^Tx = 1
11350 */
11351static
11353 SCIP* scip, /**< SCIP data structure */
11354 SCIP_CONS* cons, /**< linear constraint */
11355 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11356 int* nchgsides /**< pointer to store the amount of changed sides */
11357 )
11358{
11359 SCIP_CONSDATA* consdata;
11360 SCIP_VAR** vars;
11361 SCIP_Real* vals;
11362 SCIP_Real minval;
11363 SCIP_Real secondminval;
11364 SCIP_Real maxval;
11365 SCIP_Real lhs;
11366 SCIP_Real rhs;
11367 int nvars;
11368 int v;
11369
11370 /* we must not change a modifiable constraint in any way */
11371 if( SCIPconsIsModifiable(cons) )
11372 return SCIP_OKAY;
11373
11374 if( SCIPconsIsDeleted(cons) )
11375 return SCIP_OKAY;
11376
11377 consdata = SCIPconsGetData(cons);
11378 assert(consdata != NULL);
11379
11380 nvars = consdata->nvars;
11381
11382 /* do not check empty or bound-constraints */
11383 if( nvars < 2 )
11384 return SCIP_OKAY;
11385
11386 lhs = consdata->lhs;
11387 rhs = consdata->rhs;
11388 assert(!SCIPisInfinity(scip, -lhs));
11389 assert(!SCIPisInfinity(scip, rhs));
11390 assert(!SCIPisNegative(scip, rhs));
11391
11392 /* sides must be positive and different to detect set partition */
11393 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11394 return SCIP_OKAY;
11395
11396 vals = consdata->vals;
11397 vars = consdata->vars;
11398 assert(vars != NULL);
11399 assert(vals != NULL);
11400
11401 minval = SCIP_INVALID;
11402 secondminval = SCIP_INVALID;
11403 maxval = -SCIP_INVALID;
11404
11405 for( v = nvars - 1; v >= 0; --v )
11406 {
11407 if( SCIPvarIsBinary(vars[v]) )
11408 {
11409 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11410 {
11411 secondminval = minval;
11412 minval = vals[v];
11413 }
11414 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11415 secondminval = vals[v];
11416
11417 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11418 maxval = vals[v];
11419 }
11420 else
11421 break;
11422 }
11423
11424 /* check if all variables are binary, we can choose one, and need to choose at most one */
11425 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11426 && SCIPisGT(scip, minval + secondminval, rhs) )
11427 {
11428 /* change all coefficients to 1.0 */
11429 for( v = nvars - 1; v >= 0; --v )
11430 {
11431 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11432 }
11433 (*nchgcoefs) += nvars;
11434
11435 /* replace old right and left hand side with 1.0 */
11436 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11437 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11438 (*nchgsides) += 2;
11439 }
11440
11441 return SCIP_OKAY;
11442}
11443
11444/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11445 *
11446 * for both-sided constraints only @see rangedRowSimplify() will be called
11447 *
11448 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11449 *
11450 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11451 *
11452 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11453 *
11454 * 2. We try to remove redundant fractional parts in a constraint
11455 *
11456 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11457 *
11458 * 3. We are using the greatest common divisor for further reductions
11459 *
11460 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11461 * integral
11462 */
11463static
11465 SCIP* scip, /**< SCIP data structure */
11466 SCIP_CONS* cons, /**< linear constraint */
11467 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11468 int* nchgsides, /**< pointer to store the amount of changed sides */
11469 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11470 )
11471{
11472 SCIP_CONSDATA* consdata;
11473 SCIP_VAR** vars;
11474 SCIP_Real* vals;
11475 int* perm;
11476 SCIP_Real minactsub;
11477 SCIP_Real maxactsub;
11478 SCIP_Real siderest;
11479 SCIP_Real feastol;
11480 SCIP_Real newcoef;
11481 SCIP_Real absval;
11482 SCIP_Real minact;
11483 SCIP_Real maxact;
11484 SCIP_Real side;
11485 SCIP_Real lhs;
11486 SCIP_Real rhs;
11487 SCIP_Real lb;
11488 SCIP_Real ub;
11489 SCIP_Longint restcoef;
11490 SCIP_Longint oldgcd;
11491 SCIP_Longint rest;
11492 SCIP_Longint gcd;
11493 SCIP_Bool isminsettoinfinity;
11494 SCIP_Bool ismaxsettoinfinity;
11495 SCIP_Bool ismintight;
11496 SCIP_Bool ismaxtight;
11497 SCIP_Bool allcoefintegral;
11498 SCIP_Bool onlybin;
11499 SCIP_Bool hasrhs;
11500 SCIP_Bool haslhs;
11501 int oldnchgcoefs;
11502 int oldnchgsides;
11503 int foundbin;
11504 int candpos;
11505 int candpos2;
11506 int offsetv;
11507 int nvars;
11508 int v;
11509 int w;
11510
11511 assert(scip != NULL);
11512 assert(cons != NULL);
11513 assert(nchgcoefs != NULL);
11514 assert(nchgsides != NULL);
11515
11516 *infeasible = FALSE;
11517
11518 /* we must not change a modifiable constraint in any way */
11519 if( SCIPconsIsModifiable(cons) )
11520 return SCIP_OKAY;
11521
11522 if( SCIPconsIsDeleted(cons) )
11523 return SCIP_OKAY;
11524
11525 consdata = SCIPconsGetData(cons);
11526 assert(consdata != NULL);
11527
11528 nvars = consdata->nvars;
11529
11530 /* do not check empty or bound-constraints */
11531 if( nvars <= 2 )
11532 return SCIP_OKAY;
11533
11534 /* update maximal activity delta if necessary */
11535 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11537
11538 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11539 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11540 checkMaxActivityDelta(scip, consdata);
11541
11542 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11543 * accordingly
11544 */
11545 /* can only work with valid non-infinity activities per variable */
11546 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11547 return SCIP_OKAY;
11548
11549 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11550 * but the eventsystem seems to be full
11551 */
11552 consdata->normalized = FALSE;
11553
11554 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11555 assert(nvars == consdata->nvars);
11556
11557 if( *infeasible )
11558 return SCIP_OKAY;
11559
11560 if( !consdata->normalized )
11561 return SCIP_OKAY;
11562
11563 lhs = consdata->lhs;
11564 rhs = consdata->rhs;
11565 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11566 assert(!SCIPisNegative(scip, rhs));
11567
11568 if( !SCIPisInfinity(scip, -lhs) )
11569 haslhs = TRUE;
11570 else
11571 haslhs = FALSE;
11572
11573 if( !SCIPisInfinity(scip, rhs) )
11574 hasrhs = TRUE;
11575 else
11576 hasrhs = FALSE;
11577
11578 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11579 SCIPdebug( oldnchgsides = *nchgsides; )
11580
11581 /* @todo extend both-sided simplification */
11582 if( haslhs && hasrhs )
11583 {
11584 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11585
11586 return SCIP_OKAY;
11587 }
11588 assert(haslhs != hasrhs);
11589
11590 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11591 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11592 assert(!haslhs || !SCIPisNegative(scip, lhs));
11593
11594 /* get temporary memory to store the sorted permutation */
11595 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11596
11597 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11598 * value of their coefficients
11599 */
11600 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11601
11602 /* perform sorting after permutation array */
11603 permSortConsdata(consdata, perm, nvars);
11604 consdata->indexsorted = FALSE;
11605 consdata->coefsorted = FALSE;
11606
11607 vars = consdata->vars;
11608 vals = consdata->vals;
11609 assert(vars != NULL);
11610 assert(vals != NULL);
11611 assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11612
11613 /* free temporary memory */
11614 SCIPfreeBufferArray(scip, &perm);
11615
11616 /* only check constraints with at least two non continuous variables */
11617 if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11618 return SCIP_OKAY;
11619
11620 /* do not process constraints when all coefficients are 1.0 */
11621 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11622 return SCIP_OKAY;
11623
11624 feastol = SCIPfeastol(scip);
11625
11626 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11628
11629 /* get global activities */
11630 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11631 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
11632
11633 /* cannot work with infinite activities */
11634 if( isminsettoinfinity || ismaxsettoinfinity )
11635 return SCIP_OKAY;
11636
11637 assert(ismintight);
11638 assert(ismaxtight);
11639 assert(maxact > minact);
11640 assert(!SCIPisInfinity(scip, -minact));
11641 assert(!SCIPisInfinity(scip, maxact));
11642
11643 v = 0;
11644 offsetv = -1;
11645 side = haslhs ? lhs : rhs;
11646 minactsub = minact;
11647 maxactsub = maxact;
11648
11649 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11650 * do not need to look at the large coefficients
11651 *
11652 * e.g. all x are binary, z are positive integer
11653 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11654 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11655 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11656 *
11657 * can be changed to
11658 *
11659 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11660 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11661 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11662 */
11663
11664 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11665 * hand side, we cannot apply the extra reduction step and need to reset v
11666 *
11667 * 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
11668 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11669 * for all i is a solution
11670 *
11671 * also redundancy of variables would not be correctly determined in such a case
11672 */
11673 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11674 {
11675 v = 1;
11676
11677 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11678 {
11679 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11680 * extra step, which might have worked
11681 */
11682 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11683 {
11684 v = 0;
11685 break;
11686 }
11687
11688 ++v;
11689 }
11690
11691 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11692 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11693 if( v == nvars )
11694 return SCIP_OKAY;
11695
11696 /* cannot work with continuous variables which have a big coefficient */
11697 if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11698 return SCIP_OKAY;
11699
11700 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11701 if( SCIPisEQ(scip, side, -vals[v]) )
11702 v = 0;
11703
11704 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11705 * reduction
11706 */
11707 if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11708 v = 0;
11709
11710 if( v > 0 )
11711 {
11712 assert(v < nvars);
11713
11714 offsetv = v - 1;
11715
11716 for( w = 0; w < v; ++w )
11717 {
11718 lb = SCIPvarGetLbGlobal(vars[w]);
11719 ub = SCIPvarGetUbGlobal(vars[w]);
11720
11721 assert(vals[w] > 0);
11722
11723 /* update residual activities */
11724 maxactsub -= ub * vals[w];
11725 minactsub -= lb * vals[w];
11726 assert(maxactsub > minactsub);
11727 }
11728 }
11729 }
11730
11731 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11732 *
11733 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11734 *
11735 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11736 * to
11737 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11738 */
11739 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11740 {
11741 SCIP_Bool redundant = FALSE;
11742 SCIP_Bool numericsok;
11743 SCIP_Bool rredundant;
11744 SCIP_Bool lredundant;
11745
11746 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11747 assert(gcd >= 1);
11748
11749 if( v == 0 )
11750 {
11751 lb = SCIPvarGetLbGlobal(vars[0]);
11752 ub = SCIPvarGetUbGlobal(vars[0]);
11753
11754 /* update residual activities */
11755 if( vals[0] > 0 )
11756 {
11757 maxactsub -= ub * vals[0];
11758 minactsub -= lb * vals[0];
11759 }
11760 else
11761 {
11762 maxactsub -= lb * vals[0];
11763 minactsub -= ub * vals[0];
11764 }
11765 assert(maxactsub > minactsub);
11766 ++v;
11767 }
11768
11769 siderest = -SCIP_INVALID;
11770 allcoefintegral = TRUE;
11771
11772 /* check if some variables always fit into the given constraint */
11773 for( ; v < nvars - 1; ++v )
11774 {
11775 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11776 break;
11777
11778 if( !SCIPisIntegral(scip, vals[v]) )
11779 {
11780 allcoefintegral = FALSE;
11781 break;
11782 }
11783
11784 /* calculate greatest common divisor for all general and binary variables */
11785 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11786
11787 if( gcd == 1 )
11788 break;
11789
11790 lb = SCIPvarGetLbGlobal(vars[v]);
11791 ub = SCIPvarGetUbGlobal(vars[v]);
11792
11793 assert(!SCIPisInfinity(scip, -lb));
11794 assert(!SCIPisInfinity(scip, ub));
11795
11796 /* update residual activities */
11797 if( vals[v] > 0 )
11798 {
11799 maxactsub -= ub * vals[v];
11800 minactsub -= lb * vals[v];
11801 }
11802 else
11803 {
11804 maxactsub -= lb * vals[v];
11805 minactsub -= ub * vals[v];
11806 }
11807 assert(SCIPisGE(scip, maxactsub, minactsub));
11808
11809 if( hasrhs )
11810 {
11811 /* determine the remainder of the right hand side and the gcd */
11812 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11813 }
11814 else
11815 {
11816 /* determine the remainder of the left hand side and the gcd */
11817 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11818 if( SCIPisZero(scip, siderest) )
11819 siderest = gcd;
11820 }
11821
11822 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11823 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11824
11825 /* early termination if the activities deceed the gcd */
11826 if( offsetv == -1 && (rredundant || lredundant) )
11827 {
11828 redundant = TRUE;
11829 break;
11830 }
11831 }
11832 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11833
11834 if( !redundant )
11835 {
11836 if( hasrhs )
11837 {
11838 /* determine the remainder of the right hand side and the gcd */
11839 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11840 }
11841 else
11842 {
11843 /* determine the remainder of the left hand side and the gcd */
11844 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11845 if( SCIPisZero(scip, siderest) )
11846 siderest = gcd;
11847 }
11848 }
11849 else
11850 ++v;
11851
11852 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",
11853 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11854
11855 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11856 * reasonable absolute values */
11857 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11858 REALABS(minactsub) < MAXACTVAL;
11859
11860 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11861 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11862
11863 /* check if we can remove redundant variables */
11864 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11865 {
11866 SCIP_Real oldcoef;
11867
11868 /* double check the redundancy */
11869#ifndef NDEBUG
11870 SCIP_Real tmpminactsub = 0.0;
11871 SCIP_Real tmpmaxactsub = 0.0;
11872
11873 /* recompute residual activities */
11874 for( w = v; w < nvars; ++w )
11875 {
11876 lb = SCIPvarGetLbGlobal(vars[w]);
11877 ub = SCIPvarGetUbGlobal(vars[w]);
11878
11879 assert(!SCIPisInfinity(scip, -lb));
11880 assert(!SCIPisInfinity(scip, ub));
11881
11882 /* update residual activities */
11883 if( vals[w] > 0 )
11884 {
11885 tmpmaxactsub += ub * vals[w];
11886 tmpminactsub += lb * vals[w];
11887 }
11888 else
11889 {
11890 tmpmaxactsub += lb * vals[w];
11891 tmpminactsub += ub * vals[w];
11892 }
11893 assert(tmpmaxactsub >= tmpminactsub);
11894 }
11895
11896 if( hasrhs )
11897 {
11898 assert(offsetv == -1);
11899
11900 /* determine the remainder of the right hand side and the gcd */
11901 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11902 }
11903 else
11904 {
11905 /* determine the remainder of the left hand side and the gcd */
11906 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11907 if( SCIPisZero(scip, siderest) )
11908 siderest = gcd;
11909 }
11910
11911 /* is the redundancy really fulfilled */
11912 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11913 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11914#endif
11915
11916 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11917 nvars - v, SCIPconsGetName(cons));
11918
11919 /* remove redundant variables */
11920 for( w = nvars - 1; w >= v; --w )
11921 {
11922 SCIP_CALL( delCoefPos(scip, cons, w) );
11923 }
11924 (*nchgcoefs) += (nvars - v);
11925
11926 assert(w >= 0);
11927
11928 oldcoef = vals[w];
11929
11930 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11931 assert(vars == consdata->vars);
11932 assert(vals == consdata->vals);
11933 assert(w < consdata->nvars);
11934
11935 if( *infeasible )
11936 return SCIP_OKAY;
11937
11938 /* compute new greatest common divisor due to normalization */
11939 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11940 assert(gcd >= 1);
11941
11942 /* update side */
11943 if( hasrhs )
11944 {
11945 /* replace old with new right hand side */
11946 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11947 rhs = consdata->rhs;
11948 }
11949 else
11950 {
11951 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11952 {
11953 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11954 lhs = consdata->lhs;
11955 }
11956 else
11957 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11958 }
11959 ++(*nchgsides);
11960
11961 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11962 assert(!haslhs || !SCIPisNegative(scip, lhs));
11963
11964 /* get new constraint data */
11965 nvars = consdata->nvars;
11966 assert(nvars > 0);
11967
11968 allcoefintegral = TRUE;
11969
11970#ifndef NDEBUG
11971 /* check integrality */
11972 for( w = offsetv + 1; w < nvars; ++w )
11973 {
11974 assert(SCIPisIntegral(scip, vals[w]));
11975 }
11976#endif
11978 }
11979
11980 /* try to find a better gcd, when having large coefficients */
11981 if( offsetv >= 0 && gcd == 1 )
11982 {
11983 /* calculate greatest common divisor for all general variables */
11984 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11985
11986 if( gcd > 1 )
11987 {
11988 gcd = -1;
11989 candpos = -1;
11990
11991 for( v = nvars - 1; v > offsetv; --v )
11992 {
11993 assert(!SCIPisZero(scip, vals[v]));
11994 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11995 break;
11996
11997 if( !SCIPisIntegral(scip, vals[v]) )
11998 {
11999 allcoefintegral = FALSE;
12000 break;
12001 }
12002
12003 oldgcd = gcd;
12004
12005 if( gcd == -1 )
12006 {
12007 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12008 assert(gcd >= 1);
12009 }
12010 else
12011 {
12012 /* calculate greatest common divisor for all general and binary variables */
12013 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12014 }
12015
12016 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12017 * can stop searching
12018 */
12019 if( gcd == 1 )
12020 {
12021 if( !SCIPvarIsBinary(vars[v]) )
12022 break;
12023
12024 /* found candidate */
12025 if( candpos == -1 )
12026 {
12027 gcd = oldgcd;
12028 candpos = v;
12029 }
12030 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12031 else
12032 break;
12033 }
12034 }
12035 assert(v > offsetv || candpos > offsetv);
12036 }
12037 else
12038 candpos = -1;
12039 }
12040 else
12041 candpos = nvars - 1;
12042
12043 /* check last coefficient for integrality */
12044 if( gcd > 1 && allcoefintegral && !redundant )
12045 {
12046 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12047 allcoefintegral = FALSE;
12048 }
12049
12050 /* check for further necessary coefficient adjustments */
12051 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12052 {
12053 assert(offsetv + 1 < nvars);
12054 assert(0 <= candpos && candpos < nvars);
12055
12056 if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12057 {
12058 SCIP_Bool notchangable = FALSE;
12059
12060#ifndef NDEBUG
12061 /* check integrality */
12062 for( w = offsetv + 1; w < nvars; ++w )
12063 {
12064 assert(SCIPisIntegral(scip, vals[w]));
12065 }
12066#endif
12067
12068 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12069 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12070 {
12071 /* determine the remainder of the side and the gcd */
12072 if( hasrhs )
12073 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12074 else
12075 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12076 assert(rest >= 0);
12077 assert(rest < gcd);
12078
12079 /* determine the remainder of the coefficient candidate and the gcd */
12080 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12081 assert(restcoef >= 1);
12082 assert(restcoef < gcd);
12083
12084 if( hasrhs )
12085 {
12086 /* calculate new coefficient */
12087 if( restcoef > rest )
12088 newcoef = vals[candpos] - restcoef + gcd;
12089 else
12090 newcoef = vals[candpos] - restcoef;
12091 }
12092 else
12093 {
12094 /* calculate new coefficient */
12095 if( rest == 0 || restcoef < rest )
12096 newcoef = vals[candpos] - restcoef;
12097 else
12098 newcoef = vals[candpos] - restcoef + gcd;
12099 }
12100
12101 /* done */
12102
12103 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12104 * another with the big coefficient was set to 1
12105 */
12106 if( hasrhs && SCIPisZero(scip, newcoef) )
12107 {
12108 notchangable = TRUE;
12109 }
12110 else if( SCIPisZero(scip, newcoef) )
12111 {
12112 /* delete old redundant coefficient */
12113 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12114 ++(*nchgcoefs);
12115 }
12116 else
12117 {
12118 /* replace old with new coefficient */
12119 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12120 ++(*nchgcoefs);
12121 }
12122 }
12123 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12124 {
12125 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12126 }
12127
12128 /* correct side and big coefficients */
12129 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12130 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12131 {
12132 if( haslhs )
12133 {
12134 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12135
12136 SCIP_CALL( chgLhs(scip, cons, newcoef) );
12137 ++(*nchgsides);
12138 }
12139 else
12140 {
12141 assert(hasrhs);
12142 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12143
12144 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12145 ++(*nchgsides);
12146 }
12147
12148 /* correct coefficients up front */
12149 for( w = offsetv; w >= 0; --w )
12150 {
12151 assert(vals[w] > 0);
12152
12153 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12154 }
12155 (*nchgcoefs) += (offsetv + 1);
12156 }
12157
12158 if( !notchangable )
12159 {
12160 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12161 assert(vars == consdata->vars);
12162 assert(vals == consdata->vals);
12163
12164 if( *infeasible )
12165 return SCIP_OKAY;
12166
12167 /* get new constraint data */
12168 nvars = consdata->nvars;
12169 assert(nvars >= 2);
12170
12172
12173 lhs = consdata->lhs;
12174 rhs = consdata->rhs;
12175 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12176 assert(!haslhs || !SCIPisNegative(scip, lhs));
12177 }
12178 }
12179 }
12180 }
12181
12182 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12183 /* no continuous variables are left over */
12184 if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12185 return SCIP_OKAY;
12186
12187 onlybin = TRUE;
12188 allcoefintegral = TRUE;
12189 /* check if all variables are of binary type */
12190 for( v = nvars - 1; v >= 0; --v )
12191 {
12192 if( !SCIPvarIsBinary(vars[v]) )
12193 onlybin = FALSE;
12194 if( !SCIPisIntegral(scip, vals[v]) )
12195 allcoefintegral = FALSE;
12196 }
12197
12198 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12199 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12200 *
12201 * @todo there are some steps missing ....
12202 */
12203 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12204 {
12205 SCIP_Real val;
12206 SCIP_Real newval;
12207 SCIP_Real frac = 0.0;
12208 SCIP_Bool found = FALSE;
12209
12210 if( hasrhs )
12211 {
12212 if( allcoefintegral )
12213 {
12214 /* replace old with new right hand side */
12215 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12216 ++(*nchgsides);
12217 }
12218 else
12219 {
12220 siderest = rhs - SCIPfloor(scip, rhs);
12221
12222 /* try to round down all non-integral coefficients */
12223 for( v = nvars - 1; v >= 0; --v )
12224 {
12225 val = vals[v];
12226
12227 /* add up all possible fractional parts */
12228 if( !SCIPisIntegral(scip, val) )
12229 {
12230 lb = SCIPvarGetLbGlobal(vars[v]);
12231 ub = SCIPvarGetUbGlobal(vars[v]);
12232
12233 /* at least one bound need to be at zero */
12234 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12235 return SCIP_OKAY;
12236
12237 /* swap bounds for 'standard' form */
12238 if( !SCIPisFeasZero(scip, lb) )
12239 {
12240 ub = lb;
12241 val *= -1;
12242 }
12243
12244 found = TRUE;
12245
12246 frac += (val - SCIPfloor(scip, val)) * ub;
12247
12248 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12249 *
12250 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12251 * x3, x4 set to 1 would be infeasible but feasible after flooring
12252 */
12253 if( SCIPisGT(scip, frac, siderest) )
12254 return SCIP_OKAY;
12255 }
12256 }
12257 assert(v == -1);
12258
12259 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12260
12261 /* round rhs and coefficients to integral values */
12262 if( found )
12263 {
12264 for( v = nvars - 1; v >= 0; --v )
12265 {
12266 val = vals[v];
12267
12268 /* add the whole fractional part */
12269 if( !SCIPisIntegral(scip, val) )
12270 {
12271 lb = SCIPvarGetLbGlobal(vars[v]);
12272
12273 if( SCIPisFeasZero(scip, lb) )
12274 newval = SCIPfloor(scip, val);
12275 else
12276 newval = SCIPceil(scip, val);
12277
12278 if( SCIPisZero(scip, newval) )
12279 {
12280 /* delete old redundant coefficient */
12281 SCIP_CALL( delCoefPos(scip, cons, v) );
12282 ++(*nchgcoefs);
12283 }
12284 else
12285 {
12286 /* replace old with new coefficient */
12287 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12288 ++(*nchgcoefs);
12289 }
12290 }
12291 }
12292 }
12293
12294 /* replace old with new right hand side */
12295 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12296 ++(*nchgsides);
12297 }
12298 }
12299 else
12300 {
12301 if( allcoefintegral )
12302 {
12303 /* replace old with new left hand side */
12304 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12305 ++(*nchgsides);
12306 }
12307 else
12308 {
12309 /* cannot floor left hand side to zero */
12310 if( SCIPisLT(scip, lhs, 1.0) )
12311 return SCIP_OKAY;
12312
12313 siderest = lhs - SCIPfloor(scip, lhs);
12314
12315 /* try to round down all non-integral coefficients */
12316 for( v = nvars - 1; v >= 0; --v )
12317 {
12318 val = vals[v];
12319
12320 /* add up all possible fractional parts */
12321 if( !SCIPisIntegral(scip, val) )
12322 {
12323 lb = SCIPvarGetLbGlobal(vars[v]);
12324 ub = SCIPvarGetUbGlobal(vars[v]);
12325
12326 /* at least one bound need to be at zero */
12327 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12328 return SCIP_OKAY;
12329
12330 /* swap bounds for 'standard' form */
12331 if( !SCIPisFeasZero(scip, lb) )
12332 {
12333 ub = lb;
12334 val *= -1;
12335 }
12336
12337 /* cannot floor to zero */
12338 if( SCIPisLT(scip, val, 1.0) )
12339 return SCIP_OKAY;
12340
12341 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12342 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12343 return SCIP_OKAY;
12344
12345 found = TRUE;
12346
12347 frac += (val - SCIPfloor(scip, val)) * ub;
12348
12349 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12350 * fractional parts of the variables, we cannot tighten the coefficients
12351 *
12352 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12353 * x2-x4 set to 1 would be feasible but not after flooring
12354 */
12355 if( SCIPisGE(scip, frac, 1 + siderest) )
12356 return SCIP_OKAY;
12357 }
12358 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12359 else
12360 return SCIP_OKAY;
12361 }
12362 assert(v == -1);
12363
12364 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12365
12366 /* round lhs and coefficients to integral values */
12367 if( found )
12368 {
12369 for( v = nvars - 1; v >= 0; --v )
12370 {
12371 val = vals[v];
12372
12373 /* add the whole fractional part */
12374 if( !SCIPisIntegral(scip, val) )
12375 {
12376 lb = SCIPvarGetLbGlobal(vars[v]);
12377
12378 if( SCIPisFeasZero(scip, lb) )
12379 newval = SCIPfloor(scip, val);
12380 else
12381 newval = SCIPceil(scip, val);
12382
12383 if( SCIPisZero(scip, newval) )
12384 {
12385 /* delete old redundant coefficient */
12386 SCIP_CALL( delCoefPos(scip, cons, v) );
12387 ++(*nchgcoefs);
12388 }
12389 else
12390 {
12391 /* replace old with new coefficient */
12392 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12393 ++(*nchgcoefs);
12394 }
12395 }
12396 }
12397 }
12398
12399 /* replace old with new left hand side */
12400 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12401 ++(*nchgsides);
12402 }
12403 }
12404
12405 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12406 assert(vars == consdata->vars);
12407 assert(vals == consdata->vals);
12408
12409 if( *infeasible )
12410 return SCIP_OKAY;
12411
12412 rhs = consdata->rhs;
12413 lhs = consdata->lhs;
12414
12415 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12416 assert(!haslhs || !SCIPisNegative(scip, lhs));
12417
12419
12420 nvars = consdata->nvars;
12421 if( nvars < 2 )
12422 return SCIP_OKAY;
12423
12424 allcoefintegral = TRUE;
12425#ifndef NDEBUG
12426 /* debug check if all coefficients are really integral */
12427 for( v = nvars - 1; v >= 0; --v )
12428 assert(SCIPisIntegral(scip, vals[v]));
12429#endif
12430 }
12431
12432 /* @todo following can also work on non integral coefficients, need more investigation */
12433 /* only check constraints with integral coefficients on all integral variables */
12434 if( !allcoefintegral )
12435 return SCIP_OKAY;
12436
12437 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12438 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12439 return SCIP_OKAY;
12440
12441 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12442 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12443 return SCIP_OKAY;
12444
12445 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12446 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12447 return SCIP_OKAY;
12448
12449 assert(nvars >= 2);
12450
12451 /* start gcd procedure for all variables */
12452 do
12453 {
12454 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12455 SCIPdebug( oldnchgsides = *nchgsides; )
12456
12457 /* stop if we have two coeffcients which are one in absolute value */
12458 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12459 return SCIP_OKAY;
12460
12461 gcd = -1;
12462
12463 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12464 * because coefficients of non-binary variables might have changed to zero */
12465 if( !onlybin )
12466 {
12467 foundbin = -1;
12468 onlybin = TRUE;
12469
12470 for( v = nvars - 1; v >= 0; --v )
12471 {
12472 assert(!SCIPisZero(scip, vals[v]));
12473 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12474
12475 if( SCIPvarIsBinary(vars[v]) )
12476 {
12477 if( foundbin == -1 )
12478 foundbin = v;
12479 continue;
12480 }
12481 else
12482 onlybin = FALSE;
12483
12484 absval = REALABS(vals[v]);
12485 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12486 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12487 */
12488 assert(SCIPisFeasIntegral(scip, absval));
12489
12490 if( gcd == -1 )
12491 {
12492 gcd = (SCIP_Longint)(absval + feastol);
12493 assert(gcd >= 1);
12494 }
12495 else
12496 {
12497 /* calculate greatest common divisor for all general variables */
12498 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12499 }
12500 if( gcd == 1 )
12501 break;
12502 }
12503 }
12504 else
12505 foundbin = nvars - 1;
12506
12507 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12508 if( gcd == 1 || foundbin == -1)
12509 return SCIP_OKAY;
12510
12511 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12512
12513 candpos = -1;
12514 candpos2 = -1;
12515
12516 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12517 * change the coefficient
12518 */
12519 for( v = foundbin; v >= 0; --v )
12520 {
12521 if( onlybin || SCIPvarIsBinary(vars[v]) )
12522 {
12523 absval = REALABS(vals[v]);
12524 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12525 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12526 */
12527 assert(SCIPisFeasIntegral(scip, absval));
12528
12529 oldgcd = gcd;
12530
12531 if( gcd == -1 )
12532 {
12533 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12534 assert(gcd >= 1);
12535 }
12536 else
12537 {
12538 /* calculate greatest common divisor for all general and binary variables */
12539 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12540 }
12541
12542 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12543 * can terminate
12544 */
12545 if( gcd == 1 )
12546 {
12547 /* found candidate */
12548 if( candpos == -1 )
12549 {
12550 gcd = oldgcd;
12551 candpos = v;
12552
12553 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12554 * the coefficient change
12555 */
12556 if( onlybin && v == foundbin - 1 )
12557 candpos2 = foundbin;
12558 }
12559 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12560 else
12561 {
12562 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12563 {
12564 assert(candpos2 == nvars - 1);
12565
12566 /* take new candidates */
12567 candpos = candpos2;
12568
12569 /* recalculate gcd from scratch */
12570 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12571 assert(gcd >= 1);
12572
12573 /* calculate greatest common divisor for all general and binary variables */
12574 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12575 if( gcd == 1 )
12576 return SCIP_OKAY;
12577 }
12578 else
12579 /* cannot determine a possible coefficient for reduction */
12580 return SCIP_OKAY;
12581 }
12582 }
12583 }
12584 }
12585 assert(gcd >= 2);
12586
12587 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12588 * further
12589 */
12590 assert(candpos >= 0 && candpos < nvars);
12591
12592 /* all variables and all coefficients are integral, so the side should be too */
12593 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12594
12595 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12596 * @see normalizeCons()
12597 */
12598 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12599 assert(!haslhs || !SCIPisNegative(scip, lhs));
12600
12601 /* determine the remainder of the side and the gcd */
12602 if( hasrhs )
12603 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12604 else
12605 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12606 assert(rest >= 0);
12607 assert(rest < gcd);
12608
12609 /* determine the remainder of the coefficient candidate and the gcd */
12610 if( vals[candpos] < 0 )
12611 {
12612 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12613 assert(restcoef <= -1);
12614 restcoef += gcd;
12615 }
12616 else
12617 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12618 assert(restcoef >= 1);
12619 assert(restcoef < gcd);
12620
12621 if( hasrhs )
12622 {
12623 if( rest > 0 )
12624 {
12625 /* replace old with new right hand side */
12626 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12627 ++(*nchgsides);
12628 }
12629
12630 /* calculate new coefficient */
12631 if( restcoef > rest )
12632 newcoef = vals[candpos] - restcoef + gcd;
12633 else
12634 newcoef = vals[candpos] - restcoef;
12635 }
12636 else
12637 {
12638 if( rest > 0 )
12639 {
12640 /* replace old with new left hand side */
12641 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12642 ++(*nchgsides);
12643 }
12644
12645 /* calculate new coefficient */
12646 if( rest == 0 || restcoef < rest )
12647 newcoef = vals[candpos] - restcoef;
12648 else
12649 newcoef = vals[candpos] - restcoef + gcd;
12650 }
12651 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12652
12653 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));
12654
12655 if( SCIPisZero(scip, newcoef) )
12656 {
12657 /* delete redundant coefficient */
12658 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12659 }
12660 else
12661 {
12662 /* replace old with new coefficient */
12663 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12664 }
12665 ++(*nchgcoefs);
12666
12667 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12668 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12669 assert(vars == consdata->vars);
12670 assert(vals == consdata->vals);
12671
12672 if( *infeasible )
12673 return SCIP_OKAY;
12674
12676
12677 rhs = consdata->rhs;
12678 lhs = consdata->lhs;
12679 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12680 assert(!haslhs || !SCIPisNegative(scip, lhs));
12681
12682 nvars = consdata->nvars;
12683
12684 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));
12685 }
12686 while( nvars >= 2 );
12687
12688 return SCIP_OKAY;
12689}
12690
12691
12692/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12693 * cons0 := a * cons0 + b * cons1,
12694 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12695 * for numerical stability, we will only accept integral a and b;
12696 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12697 * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12698 */
12699static
12701 SCIP* scip, /**< SCIP data structure */
12702 SCIP_CONS* cons0, /**< (in)equality to modify */
12703 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12704 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12705 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12706 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12707 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12708 int nvarscommon, /**< number of variables, that appear in both constraints */
12709 int commonidxweight, /**< variable weight sum of common variables */
12710 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12711 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12712 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12713 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12714 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12715 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12716 )
12717{
12718 SCIP_CONSDATA* consdata0;
12719 SCIP_CONSDATA* consdata1;
12720 SCIP_Real a;
12721 SCIP_Real b;
12722 SCIP_Real aggrcoef;
12723 SCIP_Real scalarsum;
12724 SCIP_Real bestscalarsum;
12725 SCIP_Bool betterscalarsum;
12726 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12727 int varweight;
12728 int nvars;
12729 int bestvarweight;
12730 int bestnvars;
12731 int bestv;
12732 int v;
12733 int i;
12734
12735 assert(scip != NULL);
12736 assert(cons0 != NULL);
12737 assert(cons1 != NULL);
12738 assert(commonidx0 != NULL);
12739 assert(commonidx1 != NULL);
12740 assert(diffidx0minus1 != NULL);
12741 assert(diffidx1minus0 != NULL);
12742 assert(nvarscommon >= 1);
12743 assert(commonidxweight >= nvarscommon);
12744 assert(nchgcoefs != NULL);
12745 assert(aggregated != NULL);
12746
12747 assert(SCIPconsIsActive(cons0));
12748 assert(SCIPconsIsActive(cons1));
12749
12750 *infeasible = FALSE;
12751
12752 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12753
12754 /* cons0 is an (in)equality */
12755 consdata0 = SCIPconsGetData(cons0);
12756 assert(consdata0 != NULL);
12757 assert(consdata0->nvars >= 1);
12758 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12759 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12760
12761 /* cons1 is an equality */
12762 consdata1 = SCIPconsGetData(cons1);
12763 assert(consdata1 != NULL);
12764 assert(consdata1->nvars >= 1);
12765 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12766 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12767
12768 *aggregated = FALSE;
12769
12770 /* search for the best common variable such that
12771 * val1[var] * consdata0 - val0[var] * consdata1
12772 * has least weighted number of variables
12773 */
12774 bestvarweight = commonidxweight + diffidx0minus1weight;
12775 bestnvars = consdata0->nvars;
12776 bestv = -1;
12777 bestscalarsum = 0.0;
12778 commonvarlindependent = TRUE;
12779 for( v = 0; v < nvarscommon; ++v )
12780 {
12781 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12782 a = consdata1->vals[commonidx1[v]];
12783 b = -consdata0->vals[commonidx0[v]];
12784
12785 /* only try aggregation, if coefficients are integral (numerical stability) */
12787 {
12788 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12789 varweight = diffidx0minus1weight + diffidx1minus0weight;
12790 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12791 scalarsum = REALABS(a) + REALABS(b);
12792 betterscalarsum = (scalarsum < bestscalarsum);
12793 for( i = 0; i < nvarscommon
12794 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12795 {
12796 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12797 if( !SCIPisZero(scip, aggrcoef) )
12798 {
12799 varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12800 nvars++;
12801 }
12802 }
12803 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12804 {
12805 bestv = v;
12806 bestvarweight = varweight;
12807 bestnvars = nvars;
12808 bestscalarsum = scalarsum;
12809 }
12810 }
12811
12812 /* update commonvarlindependent flag, if still TRUE:
12813 * 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
12814 */
12815 if( commonvarlindependent && v > 0 )
12816 commonvarlindependent = SCIPisEQ(scip,
12817 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12818 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12819 }
12820
12821 /* if better aggregation was found, create new constraint and delete old one */
12822 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12823 {
12824 SCIP_CONS* newcons;
12825 SCIP_CONSDATA* newconsdata;
12826 SCIP_VAR** newvars;
12827 SCIP_Real* newvals;
12828 SCIP_Real newlhs;
12829 SCIP_Real newrhs;
12830 int newnvars;
12831
12832 if( bestv != -1 )
12833 {
12834 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12835 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12836 {
12837 a = consdata1->vals[commonidx1[bestv]];
12838 b = -consdata0->vals[commonidx0[bestv]];
12839 }
12840 else
12841 {
12842 a = -consdata1->vals[commonidx1[bestv]];
12843 b = consdata0->vals[commonidx0[bestv]];
12844 }
12845 assert(SCIPisIntegral(scip, a));
12846 assert(SCIPisPositive(scip, a));
12847 assert(SCIPisIntegral(scip, b));
12848 assert(!SCIPisZero(scip, b));
12849 }
12850 else
12851 {
12852 assert(commonvarlindependent);
12853 if( consdata1->vals[commonidx1[0]] > 0.0 )
12854 {
12855 a = consdata1->vals[commonidx1[0]];
12856 b = -consdata0->vals[commonidx0[0]];
12857 }
12858 else
12859 {
12860 a = -consdata1->vals[commonidx1[0]];
12861 b = consdata0->vals[commonidx0[0]];
12862 }
12863 assert(SCIPisPositive(scip, a));
12864 assert(!SCIPisZero(scip, b));
12865
12866 /* if a/b is integral, then we can easily choose integer multipliers */
12867 if( SCIPisIntegral(scip, a/b) )
12868 {
12869 if( a/b > 0 )
12870 {
12871 a /= b;
12872 b = 1.0;
12873 }
12874 else
12875 {
12876 a /= -b;
12877 b = -1.0;
12878 }
12879 }
12880
12881 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12882 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12883 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12884 }
12885
12886 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12887 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12888 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12889 SCIPdebugPrintCons(scip, cons0, NULL);
12890 SCIPdebugPrintCons(scip, cons1, NULL);
12891
12892 /* get temporary memory for creating the new linear constraint */
12893 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12894 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12895
12896 /* calculate the common coefficients, if we have not recognized linear dependency */
12897 newnvars = 0;
12898 if( !commonvarlindependent )
12899 {
12900 for( i = 0; i < nvarscommon; ++i )
12901 {
12902 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12903 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12904
12905 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12906 if( !SCIPisZero(scip, aggrcoef) )
12907 {
12908 assert(newnvars < bestnvars);
12909 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12910 newvals[newnvars] = aggrcoef;
12911 newnvars++;
12912 }
12913 }
12914 }
12915 else
12916 {
12917 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12918#ifndef NDEBUG
12919 for( i = 0; i < nvarscommon; ++i )
12920 {
12921 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12922 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12923
12924 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12925 assert(SCIPisZero(scip, aggrcoef));
12926 }
12927#endif
12928 }
12929
12930 /* calculate the coefficients appearing in cons0 but not in cons1 */
12931 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12932 {
12933 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12934
12935 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12936 assert(!SCIPisZero(scip, aggrcoef));
12937 assert(newnvars < bestnvars);
12938 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12939 newvals[newnvars] = aggrcoef;
12940 newnvars++;
12941 }
12942
12943 /* calculate the coefficients appearing in cons1 but not in cons0 */
12944 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12945 {
12946 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12947
12948 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12949 assert(!SCIPisZero(scip, aggrcoef));
12950 assert(newnvars < bestnvars);
12951 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12952 newvals[newnvars] = aggrcoef;
12953 newnvars++;
12954 }
12955 assert(newnvars == bestnvars);
12956
12957 /* calculate the new left and right hand side of the (in)equality */
12958 assert(!SCIPisInfinity(scip, -consdata1->lhs));
12959 assert(!SCIPisInfinity(scip, consdata1->rhs));
12960 if( SCIPisInfinity(scip, -consdata0->lhs) )
12961 newlhs = -SCIPinfinity(scip);
12962 else
12963 newlhs = a * consdata0->lhs + b * consdata1->lhs;
12964 if( SCIPisInfinity(scip, consdata0->rhs) )
12965 newrhs = SCIPinfinity(scip);
12966 else
12967 newrhs = a * consdata0->rhs + b * consdata1->rhs;
12968
12969 /* create the new linear constraint */
12970 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12975
12976 newconsdata = SCIPconsGetData(newcons);
12977 assert(newconsdata != NULL);
12978
12979 /* copy the upgraded flag from the old cons0 to the new constraint */
12980 newconsdata->upgraded = consdata0->upgraded;
12981
12982 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12983
12984 if( *infeasible )
12985 goto TERMINATE;
12986
12987 /* check, if we really want to use the new constraint instead of the old one:
12988 * use the new one, if the maximum norm doesn't grow too much
12989 */
12990 if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12991 {
12992 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12993 SCIPdebugPrintCons(scip, newcons, NULL);
12994
12995 /* update the statistics: we changed all coefficients */
12996 if( !consdata0->upgraded )
12997 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12998 *aggregated = TRUE;
12999
13000 /* delete the old constraint, and add the new linear constraint to the problem */
13001 SCIP_CALL( SCIPdelCons(scip, cons0) );
13002 SCIP_CALL( SCIPaddCons(scip, newcons) );
13003 }
13004
13005 TERMINATE:
13006 /* release the new constraint */
13007 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
13008
13009 /* free temporary memory */
13010 SCIPfreeBufferArray(scip, &newvals);
13011 SCIPfreeBufferArray(scip, &newvars);
13012 }
13013
13014 return SCIP_OKAY;
13015}
13016
13017/** gets the key of the given element */
13018static
13019SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
13020{ /*lint --e{715}*/
13021 /* the key is the element itself */
13022 return elem;
13023}
13024
13025/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13026 * coefficients are either equal or negated
13027 */
13028static
13029SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
13030{
13031 SCIP* scip;
13032 SCIP_CONSDATA* consdata1;
13033 SCIP_CONSDATA* consdata2;
13034 SCIP_Real minscale;
13035 SCIP_Real maxscale;
13036 int i;
13037
13038 assert(key1 != NULL);
13039 assert(key2 != NULL);
13040 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13041 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13042 assert(consdata1->indexsorted);
13043 assert(consdata2->indexsorted);
13044
13045 scip = (SCIP*)userptr;
13046 assert(scip != NULL);
13047
13048 /* if it is the same constraint we dont need to check anything */
13049 if( key1 == key2 )
13050 return TRUE;
13051
13052 /* checks trivial case */
13053 if( consdata1->nvars != consdata2->nvars )
13054 return FALSE;
13055
13056 /* tests if variables are equal */
13057 for( i = 0; i < consdata1->nvars; ++i )
13058 {
13059 if( consdata1->vars[i] != consdata2->vars[i] )
13060 {
13061 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13062 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13063 return FALSE;
13064 }
13065 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13066 }
13067
13068 /* order by maxabsval */
13069 if( consdataGetMaxAbsval(consdata1) > consdataGetMaxAbsval(consdata2) )
13070 SCIPswapPointers((void**)&consdata1, (void**)&consdata2);
13071
13072 /* initialize extremal scales */
13073 minscale = SCIPinfinity(scip);
13074 maxscale = -SCIPinfinity(scip);
13075
13076 /* test if coefficient scales are equal */
13077 for( i = 0; i < consdata1->nvars; ++i )
13078 {
13079 SCIP_Real scale = consdata2->vals[i] / consdata1->vals[i];
13080
13081 if( minscale > scale )
13082 {
13083 minscale = scale;
13084
13085 if( SCIPisLT(scip, minscale, maxscale) )
13086 return FALSE;
13087 }
13088
13089 if( maxscale < scale )
13090 {
13091 maxscale = scale;
13092
13093 if( SCIPisLT(scip, minscale, maxscale) )
13094 return FALSE;
13095 }
13096 }
13097
13098 return TRUE;
13099}
13100
13101/** returns the hash value of the key */
13102static
13103SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13104{
13105 SCIP_CONSDATA* consdata;
13106 int minidx;
13107 int mididx;
13108 int maxidx;
13109#ifndef NDEBUG
13110 SCIP* scip;
13111
13112 scip = (SCIP*)userptr;
13113 assert(scip != NULL);
13114#endif
13115
13116 assert(key != NULL);
13117 consdata = SCIPconsGetData((SCIP_CONS*)key);
13118 assert(consdata != NULL);
13119 assert(consdata->nvars > 0);
13120
13121 assert(consdata->indexsorted);
13122
13123 minidx = SCIPvarGetIndex(consdata->vars[0]);
13124 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13125 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13126
13127 /* using only the variable indices as hash, since the values are compared by epsilon */
13128 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
13129}
13130
13131/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13132 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13133 */
13134static
13136 SCIP_CONS* cons /**< linear constraint */
13137 )
13138{
13139 SCIP_CONSDATA* consdata;
13140
13141 assert(cons != NULL);
13142
13143 consdata = SCIPconsGetData(cons);
13144 assert(consdata != NULL);
13145
13146 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13147}
13148
13149/** updates the hashtable such that out of all constraints in the hashtable that are detected
13150 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13151 * and all others are removed from the hashtable and stored in the given array
13152 */
13153static
13155 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13156 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13157 * upon return will contain the constraint that should be kept */
13158 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13159 * these constraints where removed from the hashtable */
13160 int* nparallelconss /**< pointer to return number of parallel constraints */
13161 )
13162{
13163 SCIP_CONS* parallelcons;
13164 unsigned int querykey;
13165
13166 *nparallelconss = 0;
13167 querykey = getParallelConsKey(*querycons);
13168
13169 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13170 {
13171 unsigned int conskey = getParallelConsKey(parallelcons);
13172
13173 if( conskey < querykey )
13174 {
13175 parallelconss[(*nparallelconss)++] = *querycons;
13176 *querycons = parallelcons;
13177 querykey = conskey;
13178 }
13179 else
13180 {
13181 parallelconss[(*nparallelconss)++] = parallelcons;
13182 }
13183
13184 /* if the constraint that just came out of the hash table is the one that is kept,
13185 * we do not need to look into the hashtable again, since the invariant is that
13186 * in the hashtable only pair-wise non-parallel constraints are contained.
13187 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13188 * could be contained due to non-transitivity of the equality comparison.
13189 * Also we can return immediately, since parallelcons is already contained in the
13190 * hashtable and we do not need to remove and reinsert it.
13191 */
13192 if( *querycons == parallelcons )
13193 return SCIP_OKAY;
13194
13195 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13196 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13197 }
13198
13199 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13200 * comnpares equal to querycons at this point
13201 */
13202#ifndef NDEBUG
13203 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13204#else
13205 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13206#endif
13207
13208 return SCIP_OKAY;
13209}
13210
13211/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13212 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13213 */
13214static
13216 SCIP* scip, /**< SCIP data structure */
13217 BMS_BLKMEM* blkmem, /**< block memory */
13218 SCIP_CONS** conss, /**< constraint set */
13219 int nconss, /**< number of constraints in constraint set */
13220 int* firstchange, /**< pointer to store first changed constraint */
13221 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13222 int* ndelconss, /**< pointer to count number of deleted constraints */
13223 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13224 )
13225{
13226 SCIP_HASHTABLE* hashtable;
13227 SCIP_CONS** parallelconss;
13228 int nparallelconss;
13229 int hashtablesize;
13230 int c;
13231
13232 assert(scip != NULL);
13233 assert(blkmem != NULL);
13234 assert(conss != NULL);
13235 assert(firstchange != NULL);
13236 assert(cutoff != NULL);
13237 assert(ndelconss != NULL);
13238 assert(nchgsides != NULL);
13239
13240 /* create a hash table for the constraint set */
13241 hashtablesize = nconss;
13242 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13243 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13244
13245 SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13246
13247 /* check all constraints in the given set for redundancy */
13248 for( c = 0; c < nconss; ++c )
13249 {
13250 SCIP_CONS* cons0;
13251 SCIP_CONSDATA* consdata0;
13252
13253 cons0 = conss[c];
13254
13255 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13256 continue;
13257
13258 /* do not check for parallel constraints if they should not be upgraded */
13259 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13260 continue;
13261
13262 /* check for interuption */
13263 if( c % 1000 == 0 && SCIPisStopped(scip) )
13264 break;
13265
13266 /* sorts the constraint */
13267 consdata0 = SCIPconsGetData(cons0);
13268 assert(consdata0 != NULL);
13269 SCIP_CALL( consdataSort(scip, consdata0) );
13270 assert(consdata0->indexsorted);
13271
13272 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13273 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13274 * first variable is positive
13275 * Also inserts cons0 into the hashtable.
13276 */
13277 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13278
13279 if( nparallelconss != 0 )
13280 {
13281 SCIP_Real lhs;
13282 SCIP_Real rhs;
13283
13284 int i;
13285
13286 /* cons0 may have been changed in retrieveParallelConstraints() */
13287 consdata0 = SCIPconsGetData(cons0);
13288
13289 lhs = consdata0->lhs;
13290 rhs = consdata0->rhs;
13291
13292 for( i = 0; i < nparallelconss; ++i )
13293 {
13294 SCIP_CONS* consdel;
13295 SCIP_CONSDATA* consdatadel;
13296 SCIP_Real scale;
13297
13298 consdel = parallelconss[i];
13299 consdatadel = SCIPconsGetData(consdel);
13300
13301 /* do not delete constraint if it should not be upgraded */
13302 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13303 continue;
13304
13305 assert(SCIPconsIsActive(consdel));
13306 assert(!SCIPconsIsModifiable(consdel));
13307
13308 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13309 * delete old constraints afterwards
13310 */
13311 assert(consdatadel != NULL);
13312 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13313
13314 assert(consdatadel->indexsorted);
13315 assert(consdata0->vars[0] == consdatadel->vars[0]);
13316
13317 scale = consdata0->vals[0] / consdatadel->vals[0];
13318 assert(scale != 0.0);
13319
13320 /* in debug mode, check that all coefficients are equal with respect to epsilon
13321 * if the constraints are in equilibrium scale
13322 */
13323#ifndef NDEBUG
13324 {
13325 assert(consdata0->validmaxabsval);
13326 assert(consdatadel->validmaxabsval);
13327 int k;
13328 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13329 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13330
13331 for( k = 0; k < consdata0->nvars; ++k )
13332 {
13333 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13334 }
13335 }
13336#endif
13337
13338 if( scale > 0.0 )
13339 {
13340 /* the coefficients of both constraints are parallel with a positive scale */
13341 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13342 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13343 SCIPdebugPrintCons(scip, cons0, NULL);
13344 SCIPdebugPrintCons(scip, consdel, NULL);
13345
13346 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13347 lhs = MAX(scale * consdatadel->lhs, lhs);
13348
13349 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13350 rhs = MIN(scale * consdatadel->rhs, rhs);
13351 }
13352 else
13353 {
13354 /* the coefficients of both rows are negations */
13355 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13356 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13357 SCIPdebugPrintCons(scip, cons0, NULL);
13358 SCIPdebugPrintCons(scip, consdel, NULL);
13359
13360 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13361 lhs = MAX(scale * consdatadel->rhs, lhs);
13362
13363 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13364 rhs = MIN(scale * consdatadel->lhs, rhs);
13365 }
13366
13367 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13368 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13369
13370 /* delete consdel */
13371 assert( ! consdata0->upgraded || consdatadel->upgraded );
13372 SCIP_CALL( SCIPdelCons(scip, consdel) );
13373 if( !consdatadel->upgraded )
13374 (*ndelconss)++;
13375 }
13376
13377 if( SCIPisFeasLT(scip, rhs, lhs) )
13378 {
13379 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13380 *cutoff = TRUE;
13381 break;
13382 }
13383
13384 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13385 if( lhs > rhs )
13386 {
13387 rhs = (lhs + rhs)/2;
13388 lhs = rhs;
13389 }
13390
13391 /* update lhs and rhs of cons0 */
13392 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13393 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13394
13395 /* update the first changed constraint to begin the next aggregation round with */
13396 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13397 *firstchange = SCIPconsGetPos(cons0);
13398
13399 assert(SCIPconsIsActive(cons0));
13400 }
13401 }
13402#ifdef SCIP_MORE_DEBUG
13403 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13405#endif
13406
13407 SCIPfreeBufferArray(scip, &parallelconss);
13408
13409 /* free hash table */
13410 SCIPhashtableFree(&hashtable);
13411
13412 return SCIP_OKAY;
13413}
13414
13415/** compares constraint with all prior constraints for possible redundancy or aggregation,
13416 * and removes or changes constraint accordingly
13417 */
13418static
13420 SCIP* scip, /**< SCIP data structure */
13421 SCIP_CONS** conss, /**< constraint set */
13422 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13423 int chkind, /**< index of constraint to check against all prior indices upto startind */
13424 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13425 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13426 int* ndelconss, /**< pointer to count number of deleted constraints */
13427 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13428 int* nchgcoefs /**< pointer to count number of changed coefficients */
13429 )
13430{
13431 SCIP_CONS* cons0;
13432 SCIP_CONSDATA* consdata0;
13433 int* commonidx0;
13434 int* commonidx1;
13435 int* diffidx0minus1;
13436 int* diffidx1minus0;
13437 uint64_t possignature0;
13438 uint64_t negsignature0;
13439 SCIP_Bool cons0changed;
13440 SCIP_Bool cons0isequality;
13441 int diffidx1minus0size;
13442 int c;
13443 SCIP_Real cons0lhs;
13444 SCIP_Real cons0rhs;
13445 SCIP_Bool cons0upgraded;
13446
13447 assert(scip != NULL);
13448 assert(conss != NULL);
13449 assert(firstchange <= chkind);
13450 assert(cutoff != NULL);
13451 assert(ndelconss != NULL);
13452 assert(nchgsides != NULL);
13453 assert(nchgcoefs != NULL);
13454
13455 /* get the constraint to be checked against all prior constraints */
13456 cons0 = conss[chkind];
13457 assert(cons0 != NULL);
13458 assert(SCIPconsIsActive(cons0));
13459 assert(!SCIPconsIsModifiable(cons0));
13460
13461 consdata0 = SCIPconsGetData(cons0);
13462 assert(consdata0 != NULL);
13463 assert(consdata0->nvars >= 1);
13464 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13465
13466 /* sort the constraint */
13467 SCIP_CALL( consdataSort(scip, consdata0) );
13468
13469 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13470 consdataCalcSignatures(consdata0);
13471 possignature0 = consdata0->possignature;
13472 negsignature0 = consdata0->negsignature;
13473
13474 /* get temporary memory for indices of common variables */
13475 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13476 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13477 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13478 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13479 diffidx1minus0size = consdata0->nvars;
13480
13481 cons0lhs = consdata0->lhs;
13482 cons0rhs = consdata0->rhs;
13483 cons0upgraded = consdata0->upgraded;
13484
13485 /* check constraint against all prior constraints */
13486 cons0changed = consdata0->changed;
13487 consdata0->changed = FALSE;
13488 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13489 {
13490 SCIP_CONS* cons1;
13491 SCIP_CONSDATA* consdata1;
13492 uint64_t possignature1;
13493 uint64_t negsignature1;
13494 SCIP_Bool cons0dominateslhs;
13495 SCIP_Bool cons1dominateslhs;
13496 SCIP_Bool cons0dominatesrhs;
13497 SCIP_Bool cons1dominatesrhs;
13498 SCIP_Bool cons1isequality;
13499 SCIP_Bool coefsequal;
13500 SCIP_Bool coefsnegated;
13501 SCIP_Bool tryaggregation;
13502 int nvarscommon;
13503 int nvars0minus1;
13504 int nvars1minus0;
13505 int commonidxweight;
13506 int diffidx0minus1weight;
13507 int diffidx1minus0weight;
13508 int v0;
13509 int v1;
13510
13511 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13512 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13513 assert(cons0upgraded == consdata0->upgraded);
13514
13515 cons1 = conss[c];
13516
13517 /* cons1 has become inactive during presolving of constraint pairs */
13518 if( cons1 == NULL )
13519 continue;
13520
13521 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13522 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13523
13524 consdata1 = SCIPconsGetData(cons1);
13525 assert(consdata1 != NULL);
13526
13527 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13528 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13529 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13530
13531 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13532 if( !cons0changed && !consdata1->changed )
13533 continue;
13534
13535 /* if both constraints are already upgraded, skip the pair;
13536 * because changes on these constraints cannot be applied to the instance anymore */
13537 if( cons0upgraded && consdata1->upgraded )
13538 continue;
13539
13540 assert(consdata1->nvars >= 1);
13541
13542 /* sort the constraint */
13543 SCIP_CALL( consdataSort(scip, consdata1) );
13544
13545 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13546 consdataCalcSignatures(consdata1);
13547 possignature1 = consdata1->possignature;
13548 negsignature1 = consdata1->negsignature;
13549
13550 /* the signatures give a quick test to check for domination and equality of coefficients */
13551 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13552 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13553 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13554 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13555 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13556 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13557 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13558 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13559 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13560 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13561 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13562 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13563 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13564 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13565 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13566 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13567 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13568 && !coefsequal && !coefsnegated && !tryaggregation )
13569 continue;
13570
13571 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13572 if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13573 {
13574 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13575 diffidx1minus0size = consdata1->nvars;
13576 }
13577
13578 /* check consdata0 against consdata1:
13579 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13580 * consdata0 dominates consdata1 w.r.t. left hand side
13581 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13582 * consdata0 dominates consdata1 w.r.t. right hand side
13583 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13584 * ranged row (or equality)
13585 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13586 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13587 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13588 * number of continuous and integer variables are preferred:
13589 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13590 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13591 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13592 * to be positive to not switch the sense of the (in)equality cons0
13593 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13594 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13595 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13596 * to be positive to not switch the sense of the (in)equality cons1
13597 */
13598
13599 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13600 nvarscommon = 0;
13601 commonidxweight = 0;
13602 nvars0minus1 = 0;
13603 diffidx0minus1weight = 0;
13604 nvars1minus0 = 0;
13605 diffidx1minus0weight = 0;
13606 v0 = 0;
13607 v1 = 0;
13608 while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13609 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13610 || coefsequal || coefsnegated || tryaggregation) )
13611 {
13612 SCIP_VAR* var;
13613 SCIP_Real val0;
13614 SCIP_Real val1;
13615 int varcmp;
13616
13617 /* test, if variable appears in only one or in both constraints */
13618 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13619 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13620 else if( v0 < consdata0->nvars )
13621 varcmp = -1;
13622 else
13623 varcmp = +1;
13624
13625 switch( varcmp )
13626 {
13627 case -1:
13628 /* variable doesn't appear in consdata1 */
13629 var = consdata0->vars[v0];
13630 val0 = consdata0->vals[v0];
13631 val1 = 0.0;
13632 if( tryaggregation )
13633 {
13634 diffidx0minus1[nvars0minus1] = v0;
13635 nvars0minus1++;
13636 diffidx0minus1weight += getVarWeight(var);
13637 }
13638 v0++;
13639 coefsequal = FALSE;
13640 coefsnegated = FALSE;
13641 break;
13642
13643 case +1:
13644 /* variable doesn't appear in consdata0 */
13645 var = consdata1->vars[v1];
13646 val0 = 0.0;
13647 val1 = consdata1->vals[v1];
13648 if( tryaggregation )
13649 {
13650 diffidx1minus0[nvars1minus0] = v1;
13651 nvars1minus0++;
13652 diffidx1minus0weight += getVarWeight(var);
13653 }
13654 v1++;
13655 coefsequal = FALSE;
13656 coefsnegated = FALSE;
13657 break;
13658
13659 case 0:
13660 /* variable appears in both constraints */
13661 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13662 var = consdata0->vars[v0];
13663 val0 = consdata0->vals[v0];
13664 val1 = consdata1->vals[v1];
13665 if( tryaggregation )
13666 {
13667 commonidx0[nvarscommon] = v0;
13668 commonidx1[nvarscommon] = v1;
13669 nvarscommon++;
13670 commonidxweight += getVarWeight(var);
13671 }
13672 v0++;
13673 v1++;
13674 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13675 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13676 break;
13677
13678 default:
13679 SCIPerrorMessage("invalid comparison result\n");
13680 SCIPABORT();
13681 var = NULL;
13682 val0 = 0.0;
13683 val1 = 0.0;
13684 }
13685 assert(var != NULL);
13686
13687 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13688 if( SCIPisGT(scip, val0, val1) )
13689 {
13691 {
13692 cons0dominatesrhs = FALSE;
13693 cons1dominateslhs = FALSE;
13694 }
13696 {
13697 cons0dominateslhs = FALSE;
13698 cons1dominatesrhs = FALSE;
13699 }
13700 }
13701 else if( SCIPisLT(scip, val0, val1) )
13702 {
13704 {
13705 cons0dominateslhs = FALSE;
13706 cons1dominatesrhs = FALSE;
13707 }
13709 {
13710 cons0dominatesrhs = FALSE;
13711 cons1dominateslhs = FALSE;
13712 }
13713 }
13714 }
13715
13716 /* check for disaggregated ranged rows */
13717 if( coefsequal || coefsnegated )
13718 {
13719 SCIP_CONS* consstay;
13720 SCIP_CONS* consdel;
13721#ifndef NDEBUG
13722 SCIP_CONSDATA* consdatastay;
13723#endif
13724 SCIP_CONSDATA* consdatadel;
13725 SCIP_Real lhs;
13726 SCIP_Real rhs;
13727 int consinddel;
13728
13729 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13730 * best left and right hand sides; delete the old constraints afterwards
13731 */
13732 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13733 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13734 SCIPdebugPrintCons(scip, cons0, NULL);
13735 SCIPdebugPrintCons(scip, cons1, NULL);
13736
13737 if( coefsequal )
13738 {
13739 /* the coefficients of both rows are equal */
13740 lhs = MAX(consdata0->lhs, consdata1->lhs);
13741 rhs = MIN(consdata0->rhs, consdata1->rhs);
13742 }
13743 else
13744 {
13745 /* the coefficients of both rows are negations */
13746 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13747 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13748 }
13749 if( SCIPisFeasLT(scip, rhs, lhs) )
13750 {
13751 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13752 *cutoff = TRUE;
13753 break;
13754 }
13755
13756 /* check which constraint has to stay;
13757 * changes applied to an upgraded constraint will not be considered in the instance */
13758 if( consdata0->upgraded )
13759 {
13760 assert(!consdata1->upgraded);
13761 consstay = cons1;
13762#ifndef NDEBUG
13763 consdatastay = consdata1;
13764#endif
13765
13766 consdel = cons0;
13767 consdatadel = consdata0;
13768 consinddel = chkind;
13769 }
13770 else
13771 {
13772 consstay = cons0;
13773#ifndef NDEBUG
13774 consdatastay = consdata0;
13775#endif
13776
13777 consdel = cons1;
13778 consdatadel = consdata1;
13779 consinddel = c;
13780 }
13781
13782 /* update the sides of consstay */
13783 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13784 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13785 if( !consdata0->upgraded )
13786 {
13787 assert(consstay == cons0);
13788 cons0lhs = consdata0->lhs;
13789 cons0rhs = consdata0->rhs;
13790 }
13791
13792 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13793 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13794
13795 assert( !consdatastay->upgraded );
13796 /* delete consdel */
13797 SCIP_CALL( SCIPdelCons(scip, consdel) );
13798 conss[consinddel] = NULL;
13799 if( !consdatadel->upgraded )
13800 (*ndelconss)++;
13801 continue;
13802 }
13803
13804 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13805 * redundant
13806 */
13807 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13808 {
13809 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13810 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13811 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13812 SCIPdebugPrintCons(scip, cons0, NULL);
13813 SCIPdebugPrintCons(scip, cons1, NULL);
13814
13815 /* check for infeasibility */
13816 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->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, -consdata0->lhs) )
13825 {
13826 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13827 cons0lhs = consdata0->lhs;
13828 cons0isequality = FALSE;
13829 if( !consdata0->upgraded )
13830 {
13831 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13832 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13833
13834 (*nchgsides)++;
13835 }
13836 }
13837 }
13838 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13839 {
13840 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13841 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13842 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13843 SCIPdebugPrintCons(scip, cons1, NULL);
13844 SCIPdebugPrintCons(scip, cons0, NULL);
13845
13846 /* check for infeasibility */
13847 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13848 {
13849 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13850 *cutoff = TRUE;
13851 break;
13852 }
13853
13854 /* remove redundant left hand side */
13855 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13856 {
13857 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13858 cons1isequality = FALSE;
13859 if( !consdata1->upgraded )
13860 {
13861 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13862 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13863
13864 (*nchgsides)++;
13865 }
13866 }
13867 }
13868 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13869 {
13870 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13871 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13872 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13873 SCIPdebugPrintCons(scip, cons0, NULL);
13874 SCIPdebugPrintCons(scip, cons1, NULL);
13875
13876 /* check for infeasibility */
13877 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->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, consdata0->rhs) )
13886 {
13887 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13888 cons0rhs = consdata0->rhs;
13889 cons0isequality = FALSE;
13890 if( !consdata0->upgraded )
13891 {
13892 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13893 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13894
13895 (*nchgsides)++;
13896 }
13897 }
13898 }
13899 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13900 {
13901 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13902 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13903 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13904 SCIPdebugPrintCons(scip, cons1, NULL);
13905 SCIPdebugPrintCons(scip, cons0, NULL);
13906
13907 /* check for infeasibility */
13908 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13909 {
13910 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13911 *cutoff = TRUE;
13912 break;
13913 }
13914
13915 /* remove redundant right hand side */
13916 if( !SCIPisInfinity(scip, consdata1->rhs) )
13917 {
13918 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13919 cons1isequality = FALSE;
13920 if( !consdata1->upgraded )
13921 {
13922 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13923 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13924
13925 (*nchgsides)++;
13926 }
13927 }
13928 }
13929
13930 /* check for now redundant constraints */
13931 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13932 {
13933 /* consdata0 became redundant */
13934 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13935 SCIP_CALL( SCIPdelCons(scip, cons0) );
13936 conss[chkind] = NULL;
13937 if( !consdata0->upgraded )
13938 {
13939 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13940 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13941
13942 (*ndelconss)++;
13943 }
13944 continue;
13945 }
13946 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13947 {
13948 /* consdata1 became redundant */
13949 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13950 SCIP_CALL( SCIPdelCons(scip, cons1) );
13951 conss[c] = NULL;
13952 if( !consdata1->upgraded )
13953 {
13954 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13955 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13956
13957 (*ndelconss)++;
13958 }
13959 continue;
13960 }
13961
13962 /* check, if we want to aggregate an (in)equality with an equality:
13963 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13964 */
13965 if( tryaggregation )
13966 {
13967 SCIP_Bool aggregated;
13968
13969 assert(consdata0->nvars == nvarscommon + nvars0minus1);
13970 assert(consdata1->nvars == nvarscommon + nvars1minus0);
13971
13972 aggregated = FALSE;
13973 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13974 {
13975 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13976 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13977 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13978 nchgcoefs, &aggregated, cutoff) );
13979
13980 if( *cutoff )
13981 break;
13982
13983 /* update array of active constraints */
13984 if( aggregated )
13985 {
13986 assert(!SCIPconsIsActive(cons0));
13987 assert(SCIPconsIsActive(cons1));
13988 conss[chkind] = NULL;
13989 }
13990 }
13991 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13992 {
13993 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13994 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13995 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13996 nchgcoefs, &aggregated, cutoff) );
13997
13998 if( *cutoff )
13999 break;
14000
14001 /* update array of active constraints */
14002 if( aggregated )
14003 {
14004 assert(!SCIPconsIsActive(cons1));
14005 assert(SCIPconsIsActive(cons0));
14006 conss[c] = NULL;
14007 }
14008 }
14009 }
14010 }
14011
14012 /* free temporary memory */
14013 SCIPfreeBufferArray(scip, &diffidx1minus0);
14014 SCIPfreeBufferArray(scip, &diffidx0minus1);
14015 SCIPfreeBufferArray(scip, &commonidx1);
14016 SCIPfreeBufferArray(scip, &commonidx0);
14017
14018 return SCIP_OKAY;
14019}
14020
14021/** do stuffing presolving on a single constraint */
14022static
14024 SCIP* scip, /**< SCIP data structure */
14025 SCIP_CONS* cons, /**< linear constraint */
14026 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14027 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14028 * constraints using the cheapest variable? */
14029 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14030 int* nfixedvars, /**< pointer to count the total number of fixed variables */
14031 int* nchgbds /**< pointer to count the total number of tightened bounds */
14032 )
14033{
14034 SCIP_CONSDATA* consdata;
14035 SCIP_Real* ratios;
14036 int* varpos;
14037 SCIP_Bool* swapped;
14038 SCIP_VAR** vars;
14039 SCIP_Real* vals;
14040 SCIP_VAR* var;
14041 SCIP_Real lb;
14042 SCIP_Real ub;
14043 SCIP_Real minactivity;
14044 SCIP_Real maxactivity;
14045 SCIP_Real maxcondactivity;
14046 SCIP_Real mincondactivity;
14047 SCIP_Real rhs;
14048 SCIP_Real val;
14049 SCIP_Real obj;
14050 SCIP_Real factor;
14051 SCIP_Bool isminacttight;
14052 SCIP_Bool ismaxacttight;
14053 SCIP_Bool isminsettoinfinity;
14054 SCIP_Bool ismaxsettoinfinity;
14055 SCIP_Bool tryfixing;
14056 int nsingletons;
14057 int idx;
14058 int v;
14059 int nvars;
14060
14061 assert(scip != NULL);
14062 assert(cons != NULL);
14063 assert(nfixedvars != NULL);
14064
14065 consdata = SCIPconsGetData(cons);
14066
14067 /* we only want to run for inequalities */
14068 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14069 return SCIP_OKAY;
14070
14071 if( singlevarstuffing )
14072 {
14073 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
14074 &isminsettoinfinity, &ismaxsettoinfinity);
14075 }
14076 else
14077 {
14078 minactivity = SCIP_INVALID;
14079 maxactivity = SCIP_INVALID;
14080 isminsettoinfinity = FALSE;
14081 ismaxsettoinfinity = FALSE;
14082 }
14083
14084 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14085 * the new maxactivity is minus the old minactivity then
14086 */
14087 if( SCIPisInfinity(scip, consdata->rhs) )
14088 {
14089 rhs = -consdata->lhs;
14090 factor = -1.0;
14091 maxactivity = -minactivity;
14092 ismaxsettoinfinity = isminsettoinfinity;
14093 }
14094 else
14095 {
14096 assert(SCIPisInfinity(scip, -consdata->lhs));
14097 rhs = consdata->rhs;
14098 factor = 1.0;
14099 }
14100
14101 nvars = consdata->nvars;
14102 vars = consdata->vars;
14103 vals = consdata->vals;
14104
14105 /* check for continuous singletons */
14106 if( singletonstuffing )
14107 {
14108 for( v = 0; v < nvars; ++v )
14109 {
14110 var = vars[v];
14111
14114 break;
14115 }
14116 }
14117 else
14118 /* we don't want to go into the next block */
14119 v = nvars;
14120
14121 /* a singleton was found -> perform singleton variable stuffing */
14122 if( v < nvars )
14123 {
14124 assert(singletonstuffing);
14125
14126 SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14127 SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14128 SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14129
14130 tryfixing = TRUE;
14131 nsingletons = 0;
14132 mincondactivity = 0.0;
14133 maxcondactivity = 0.0;
14134
14135 for( v = 0; v < nvars; ++v )
14136 {
14137 var = vars[v];
14138 lb = SCIPvarGetLbGlobal(var);
14139 ub = SCIPvarGetUbGlobal(var);
14140 obj = SCIPvarGetObj(var);
14141 val = factor * vals[v];
14142
14143 assert(!SCIPisZero(scip, val));
14144
14145 /* the variable is a singleton and continuous */
14148 {
14149 if( SCIPisNegative(scip, obj) && val > 0 )
14150 {
14151 /* case 1: obj < 0 and coef > 0 */
14152 if( SCIPisInfinity(scip, -lb) )
14153 {
14154 tryfixing = FALSE;
14155 break;
14156 }
14157
14158 maxcondactivity += val * lb;
14159 mincondactivity += val * lb;
14160 swapped[v] = FALSE;
14161 ratios[nsingletons] = obj / val;
14162 varpos[nsingletons] = v;
14163 nsingletons++;
14164 }
14165 else if( SCIPisPositive(scip, obj) && val < 0 )
14166 {
14167 /* case 2: obj > 0 and coef < 0 */
14168 if( SCIPisInfinity(scip, ub) )
14169 {
14170 tryfixing = FALSE;
14171 break;
14172 }
14173 /* multiply column by (-1) to become case 1.
14174 * now bounds are swapped: ub := -lb, lb := -ub
14175 */
14176
14177 maxcondactivity += val * ub;
14178 mincondactivity += val * ub;
14179 swapped[v] = TRUE;
14180 ratios[nsingletons] = obj / val;
14181 varpos[nsingletons] = v;
14182 nsingletons++;
14183 }
14184 else if( val > 0 )
14185 {
14186 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14187 * we only consider the lower bound for the constants
14188 */
14189 assert(!SCIPisNegative(scip, obj));
14190
14191 if( SCIPisInfinity(scip, -lb) )
14192 {
14193 /* maybe unbounded */
14194 tryfixing = FALSE;
14195 break;
14196 }
14197
14198 maxcondactivity += val * lb;
14199 mincondactivity += val * lb;
14200 }
14201 else
14202 {
14203 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14204 * we only consider the upper bound for the constants
14205 */
14206 assert(!SCIPisPositive(scip, obj));
14207 assert(val < 0);
14208
14209 if( SCIPisInfinity(scip, ub) )
14210 {
14211 /* maybe unbounded */
14212 tryfixing = FALSE;
14213 break;
14214 }
14215
14216 maxcondactivity += val * ub;
14217 mincondactivity += val * ub;
14218 }
14219 }
14220 else
14221 {
14222 /* consider contribution of discrete variables, non-singleton
14223 * continuous variables and variables with more than one lock
14224 */
14225 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14226 {
14227 tryfixing = FALSE;
14228 break;
14229 }
14230
14231 if( val > 0 )
14232 {
14233 maxcondactivity += val * ub;
14234 mincondactivity += val * lb;
14235 }
14236 else
14237 {
14238 maxcondactivity += val * lb;
14239 mincondactivity += val * ub;
14240 }
14241 }
14242 }
14243 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14244 {
14245 SCIP_Real delta;
14246 SCIP_Bool tightened;
14247#ifdef SCIP_DEBUG
14248 int oldnfixedvars = *nfixedvars;
14249 int oldnchgbds = *nchgbds;
14250#endif
14251
14252 SCIPsortRealInt(ratios, varpos, nsingletons);
14253
14254 /* verify which singleton continuous variables can be fixed */
14255 for( v = 0; v < nsingletons; ++v )
14256 {
14257 idx = varpos[v];
14258 var = vars[idx];
14259 val = factor * vals[idx];
14260 lb = SCIPvarGetLbGlobal(var);
14261 ub = SCIPvarGetUbGlobal(var);
14262
14263 assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14264 assert((val < 0) == swapped[idx]);
14265 val = REALABS(val);
14266
14267 /* stop fixing if variable bounds are not finite */
14268 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14269 break;
14270
14274
14275 /* calculate the change in the row activities if this variable changes
14276 * its value from its worst to its best bound
14277 */
14278 if( swapped[idx] )
14279 delta = -(lb - ub) * val;
14280 else
14281 delta = (ub - lb) * val;
14282
14283 assert(!SCIPisNegative(scip, delta));
14284
14285 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14286 {
14287 if( swapped[idx] )
14288 {
14289 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14290 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14291 }
14292 else
14293 {
14294 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14295 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14296 }
14297
14298 if( *cutoff )
14299 break;
14300 if( tightened )
14301 {
14302 (*nfixedvars)++;
14303 }
14304 }
14305 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14306 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14307 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14308 * troubles in case of large bounds.
14309 */
14310 else if( SCIPisLE(scip, rhs, mincondactivity) )
14311 {
14312 if( swapped[idx] )
14313 {
14314 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14315 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14316 }
14317 else
14318 {
14319 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14320 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14321 }
14322
14323 if( *cutoff )
14324 break;
14325 if( tightened )
14326 {
14327 (*nfixedvars)++;
14328 }
14329 }
14330
14331 maxcondactivity += delta;
14332 mincondactivity += delta;
14333 }
14334
14335#ifdef SCIP_DEBUG
14336 if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14337 {
14338 SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14339 }
14340#endif
14341 }
14342
14343 SCIPfreeBufferArray(scip, &swapped);
14344 SCIPfreeBufferArray(scip, &ratios);
14345 SCIPfreeBufferArray(scip, &varpos);
14346 }
14347
14348 /* perform single-variable stuffing:
14349 * for a linear inequality
14350 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14351 * with a_i > 0 and objective coefficients c_i < 0,
14352 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14353 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14354 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14355 * is redundant.
14356 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14357 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14358 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14359 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14360 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14361 * upper bound.
14362 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14363 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14364 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14365 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14366 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14367 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14368 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14369 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14370 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14371 * c_k * ceil((maxactivity - rhs)/val) is still better than
14372 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14373 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14374 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14375 * sign of coefficients in constraint and objective prevent the use of this method.
14376 */
14377 if( singlevarstuffing && !ismaxsettoinfinity )
14378 {
14379 SCIP_Real bestratio = -SCIPinfinity(scip);
14380 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14381 SCIP_Real ratio;
14382 int bestindex = -1;
14383 int bestuplocks = 0;
14384 int bestdownlocks = 1;
14385 int downlocks;
14386 int uplocks;
14387 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14388 SCIPdebug( int oldnchgbds = *nchgbds; )
14389
14390 /* loop over all variables to identify the best and second-best ratio */
14391 for( v = 0; v < nvars; ++v )
14392 {
14393 var = vars[v];
14394 obj = SCIPvarGetObj(var);
14395 val = factor * vals[v];
14396
14397 assert(!SCIPisZero(scip, val));
14398
14399 ratio = obj / val;
14400
14401 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14402 if( !SCIPisNegative(scip, ratio) )
14403 {
14404 bestindex = -1;
14405 break;
14406 }
14407
14408 if( val > 0 )
14409 {
14412 }
14413 else
14414 {
14417 }
14418
14419 /* better ratio, update best candidate
14420 * @todo use some tolerance
14421 * @todo check size of domain and updated ratio for integer variables already?
14422 */
14423 if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14424 || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14426 {
14427 /* best index becomes second-best*/
14428 if( bestindex != -1 )
14429 {
14430 /* second-best index must not have more than 1 uplock */
14431 if( bestuplocks > 1 )
14432 {
14433 bestindex = -1;
14434 break;
14435 }
14436 else
14437 {
14438 secondbestratio = bestratio;
14439 }
14440 }
14441 bestdownlocks = downlocks;
14442 bestuplocks = uplocks;
14443 bestratio = ratio;
14444 bestindex = v;
14445
14446 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14447 * if it is not the best, it has too many uplocks -> not applicable
14448 */
14449 if( bestdownlocks > 0 && bestuplocks > 1 )
14450 {
14451 bestindex = -1;
14452 break;
14453 }
14454 }
14455 else
14456 {
14457 /* non-best index must not have more than 1 uplock */
14458 if( uplocks > 1 )
14459 {
14460 bestindex = -1;
14461 break;
14462 }
14463 /* update second-best ratio */
14464 if( ratio > secondbestratio )
14465 {
14466 secondbestratio = ratio;
14467 }
14468 }
14469 }
14470
14471 /* check if we can apply single variable stuffing */
14472 if( bestindex != -1 && bestdownlocks == 0 )
14473 {
14474 SCIP_Bool tightened = FALSE;
14475 SCIP_Real bounddelta;
14476
14477 var = vars[bestindex];
14478 obj = SCIPvarGetObj(var);
14479 val = factor * vals[bestindex];
14480 lb = SCIPvarGetLbGlobal(var);
14481 ub = SCIPvarGetUbGlobal(var);
14482 tryfixing = TRUE;
14483
14484 if( val < 0 )
14485 {
14486 assert(!SCIPisNegative(scip, obj));
14487
14488 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14489 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14490 {
14491 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14492 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14493 assert(SCIPisPositive(scip, activitydelta));
14494
14495 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14496
14497 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14498 assert(SCIPisPositive(scip, bounddelta));
14499 }
14500 else
14501 bounddelta = (maxactivity - rhs)/-val;
14502
14503 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14504
14505 if( tryfixing )
14506 {
14508
14509 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14510 {
14511 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14512 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14513 }
14514 else
14515 {
14516 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14517 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14518 }
14519 }
14520 }
14521 else
14522 {
14523 assert(!SCIPisPositive(scip, obj));
14524
14525 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14526 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14527 {
14528 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14529 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14530 assert(SCIPisPositive(scip, activitydelta));
14531
14532 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14533
14534 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14535 assert(SCIPisPositive(scip, bounddelta));
14536 }
14537 else
14538 bounddelta = (maxactivity - rhs)/val;
14539
14540 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14541
14542 if( tryfixing )
14543 {
14545
14546 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14547 {
14548 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14549 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14550 }
14551 else
14552 {
14553 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14554 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14555 }
14556 }
14557 }
14558
14559 if( *cutoff )
14560 return SCIP_OKAY;
14561 if( tightened )
14562 {
14564 ++(*nfixedvars);
14565 else
14566 ++(*nchgbds);
14567
14568 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14569 for( v = 0; v < nvars; ++v )
14570 {
14571 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14572 SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14575 SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14576 }
14577 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14578
14579 for( v = 0; v < nvars; ++v )
14580 {
14581 if( v == bestindex )
14582 continue;
14583
14584 if( factor * vals[v] < 0 )
14585 {
14586 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14587 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14588 SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14589 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14590 }
14591 else
14592 {
14593 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14594 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14595 SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14596 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14597 }
14598
14599 if( *cutoff )
14600 return SCIP_OKAY;
14601 if( tightened )
14602 ++(*nfixedvars);
14603 }
14604 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14605 }
14606 }
14607 }
14608
14609 return SCIP_OKAY;
14610}
14611
14612/** applies full dual presolving on variables that only appear in linear constraints */
14613static
14615 SCIP* scip, /**< SCIP data structure */
14616 SCIP_CONS** conss, /**< constraint set */
14617 int nconss, /**< number of constraints */
14618 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14619 int* nchgbds, /**< pointer to count the number of bound changes */
14620 int* nchgvartypes /**< pointer to count the number of variable type changes */
14621 )
14622{
14623 SCIP_Real* redlb;
14624 SCIP_Real* redub;
14625 int* nlocksdown;
14626 int* nlocksup;
14627 SCIP_Bool* isimplint;
14628 SCIP_VAR** origvars;
14629 SCIP_VAR** vars;
14630 SCIP_VAR** conscontvars;
14631 int nvars;
14632 int nbinvars;
14633 int nintvars;
14634 int ncontvars;
14635 int v;
14636 int c;
14637
14638 /* we calculate redundancy bounds with the following meaning:
14639 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14640 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14641 * then:
14642 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14643 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14644 */
14645
14646 /* Additionally, we detect continuous variables that are implicitly integral.
14647 * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14648 * and all constraints (including the bounds as trivial constraints) in which:
14649 * c_j > 0: the variable is down-locked,
14650 * c_j < 0: the variable is up-locked,
14651 * c_j = 0: the variable appears
14652 * have, apart from j, only integer variables with integral coefficients and integral sides.
14653 * This is because then, the value of the variable is either determined by one of its bounds or
14654 * by one of these constraints, and in all cases, the value of the variable is integral.
14655 */
14656
14657 assert(scip != NULL);
14658 assert(nconss == 0 || conss != NULL);
14659 assert(nchgbds != NULL);
14660 assert(!SCIPinProbing(scip));
14661
14662 /* get active variables */
14663 nvars = SCIPgetNVars(scip);
14664 origvars = SCIPgetVars(scip);
14665
14666 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14667 nbinvars = SCIPgetNBinVars(scip);
14668 if( nbinvars == nvars )
14669 return SCIP_OKAY;
14670
14671 /* get number of continuous variables */
14672 ncontvars = SCIPgetNContVars(scip);
14673 nintvars = nvars - ncontvars;
14674
14675 /* copy the variable array since this array might change during the curse of this algorithm */
14676 nvars = nvars - nbinvars;
14677 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14678
14679 /* allocate temporary memory */
14680 SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14681 SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14682 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14683 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14684 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14685 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14686
14687 /* initialize redundancy bounds */
14688 for( v = 0; v < nvars; ++v )
14689 {
14690 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14691 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14692 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14693 }
14694 BMSclearMemoryArray(nlocksdown, nvars);
14695 BMSclearMemoryArray(nlocksup, nvars);
14696
14697 /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14698 * We better not use SCIPisFeasIntegral() in these checks.
14699 */
14700 for( v = 0; v < ncontvars; v++ )
14701 {
14702 SCIP_VAR* var;
14703 SCIP_Real obj;
14704 SCIP_Real lb;
14705 SCIP_Real ub;
14706
14707 var = vars[v + nintvars - nbinvars];
14708 lb = SCIPvarGetLbGlobal(var);
14709 ub = SCIPvarGetUbGlobal(var);
14710
14711 obj = SCIPvarGetObj(var);
14712 if( SCIPisZero(scip, obj) )
14713 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14714 else
14715 {
14716 if( SCIPisPositive(scip, obj) )
14717 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14718 else
14719 {
14720 assert(SCIPisNegative(scip, obj));
14721 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14722 }
14723 }
14724 }
14725
14726 /* scan all constraints */
14727 for( c = 0; c < nconss; ++c )
14728 {
14729 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14730 * part of checked disjunctions)
14731 */
14732 if( SCIPconsIsLocked(conss[c]) )
14733 {
14734 SCIP_CONSDATA* consdata;
14735 SCIP_Bool lhsexists;
14736 SCIP_Bool rhsexists;
14737 SCIP_Bool hasimpliedpotential;
14738 SCIP_Bool integralcoefs;
14739 int nlockspos;
14740 int contvarpos;
14741 int nconscontvars;
14742 int i;
14743
14744 consdata = SCIPconsGetData(conss[c]);
14745 assert(consdata != NULL);
14746
14747 /* get number of times the constraint was locked */
14748 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14749
14750 /* we do not want to include constraints with locked negation (this would be too weird) */
14751 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14752 {
14753 /* mark all continuous variables as not being implicit integral */
14754 for( i = 0; i < consdata->nvars; ++i )
14755 {
14756 SCIP_VAR* var;
14757
14758 var = consdata->vars[i];
14760 {
14761 int contv;
14762 contv = SCIPvarGetProbindex(var) - nintvars;
14763 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14764 isimplint[contv] = FALSE;
14765 }
14766 }
14767 continue;
14768 }
14769
14770 /* check for existing sides */
14771 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14772 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14773
14774 /* count locks and update redundancy bounds */
14775 contvarpos = -1;
14776 nconscontvars = 0;
14777 hasimpliedpotential = FALSE;
14778 integralcoefs = !SCIPconsIsModifiable(conss[c]);
14779
14780 for( i = 0; i < consdata->nvars; ++i )
14781 {
14782 SCIP_VAR* var;
14783 SCIP_Real val;
14784 SCIP_Real minresactivity;
14785 SCIP_Real maxresactivity;
14786 SCIP_Real newredlb;
14787 SCIP_Real newredub;
14788 SCIP_Bool ismintight;
14789 SCIP_Bool ismaxtight;
14790 SCIP_Bool isminsettoinfinity;
14791 SCIP_Bool ismaxsettoinfinity;
14792 int arrayindex;
14793
14794 var = consdata->vars[i];
14795 assert(var != NULL);
14796 val = consdata->vals[i];
14797 assert(!SCIPisZero(scip, val));
14798
14799 /* check if still all integer variables have integral coefficients */
14800 if( SCIPvarIsIntegral(var) )
14801 integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14802
14803 /* we do not need to process binary variables */
14804 if( SCIPvarIsBinary(var) )
14805 continue;
14806
14807 if( SCIPconsIsModifiable(conss[c]) )
14808 {
14809 minresactivity = -SCIPinfinity(scip);
14810 maxresactivity = SCIPinfinity(scip);
14811 isminsettoinfinity = TRUE;
14812 ismaxsettoinfinity = TRUE;
14813 }
14814 else
14815 {
14816 /* calculate residual activity bounds if variable would be fixed to zero */
14817 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14818 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
14819
14820 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14821 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14822 * This is needed, because we do not want to rely on relaxed finite resactivities.
14823 */
14824 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
14825
14826 /* check minresactivity for reliability */
14827 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14828 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14829
14830 /* check maxresactivity for reliability */
14831 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14832 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14833 }
14834
14835 arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14836
14837 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14838
14839 newredlb = redlb[arrayindex];
14840 newredub = redub[arrayindex];
14841 if( val > 0.0 )
14842 {
14843 if( lhsexists )
14844 {
14845 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14846 nlocksdown[arrayindex] += nlockspos;
14847 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14848 }
14849 if( rhsexists )
14850 {
14851 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14852 nlocksup[arrayindex] += nlockspos;
14853 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14854 }
14855 }
14856 else
14857 {
14858 if( lhsexists )
14859 {
14860 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14861 nlocksup[arrayindex] += nlockspos;
14862 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14863 }
14864 if( rhsexists )
14865 {
14866 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14867 nlocksdown[arrayindex] += nlockspos;
14868 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14869 }
14870 }
14871
14872 /* if the variable is integer, we have to round the value to the next integral value */
14873 if( SCIPvarIsIntegral(var) )
14874 {
14875 if( !SCIPisInfinity(scip, newredlb) )
14876 newredlb = SCIPceil(scip, newredlb);
14877 if( !SCIPisInfinity(scip, -newredub) )
14878 newredub = SCIPfloor(scip, newredub);
14879 }
14880
14881 /* update redundancy bounds */
14882 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14883 redub[arrayindex] = MIN(redub[arrayindex], newredub);
14884
14885 /* collect the continuous variables of the constraint */
14887 {
14888 int contv;
14889
14890 assert(nconscontvars < ncontvars);
14891 contvarpos = i;
14892 conscontvars[nconscontvars] = var;
14893 nconscontvars++;
14894
14895 contv = SCIPvarGetProbindex(var) - nintvars;
14896 assert(0 <= contv && contv < ncontvars);
14897 hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14898 }
14899 }
14900
14901 /* update implicit integer status of continuous variables */
14902 if( hasimpliedpotential )
14903 {
14904 if( nconscontvars > 1 || !integralcoefs )
14905 {
14906 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14907 * none of the continuous variables is implicit integer
14908 */
14909 for( i = 0; i < nconscontvars; i++ )
14910 {
14911 int contv;
14912 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14913 assert(0 <= contv && contv < ncontvars);
14914 isimplint[contv] = FALSE;
14915 }
14916 }
14917 else
14918 {
14919 SCIP_VAR* var;
14920 SCIP_Real val;
14921 SCIP_Real absval;
14922 int contv;
14923
14924 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14925 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14926 * side(s) of the constraint is integral
14927 */
14928 assert(nconscontvars == 1);
14929 assert(0 <= contvarpos && contvarpos < consdata->nvars);
14930 var = consdata->vars[contvarpos];
14931 val = consdata->vals[contvarpos];
14932 contv = SCIPvarGetProbindex(var) - nintvars;
14933 assert(0 <= contv && contv < ncontvars);
14934 assert(isimplint[contv]);
14935
14936 absval = REALABS(val);
14937 if( !SCIPisEQ(scip, absval, 1.0) )
14938 isimplint[contv] = FALSE;
14939 else
14940 {
14941 SCIP_Real obj;
14942
14943 obj = SCIPvarGetObj(var);
14944 if( obj * val >= 0.0 && lhsexists )
14945 {
14946 /* the variable may be blocked by the constraint's left hand side */
14947 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14948 }
14949 if( obj * val <= 0.0 && rhsexists )
14950 {
14951 /* the variable may be blocked by the constraint's left hand side */
14952 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14953 }
14954 }
14955 }
14956 }
14957 }
14958 }
14959
14960 /* check if any bounds can be tightened due to optimality */
14961 for( v = 0; v < nvars; ++v )
14962 {
14963 SCIP_VAR* var;
14964 SCIP_Real obj;
14965 SCIP_Bool infeasible;
14966 SCIP_Bool tightened;
14967
14968 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14969 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14970 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14971
14972 var = vars[v];
14973 obj = SCIPvarGetObj(var);
14974 if( !SCIPisPositive(scip, -obj) )
14975 {
14976 /* making the variable as small as possible does not increase the objective:
14977 * check if all down locks of the variables are due to linear constraints;
14978 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
14979 * constraints redundant is huge, we better do nothing for numerical reasons
14980 */
14982 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
14983 && !SCIPisHugeValue(scip, -redlb[v])
14984 && redlb[v] < SCIPvarGetUbGlobal(var) )
14985 {
14986 SCIP_Real ub;
14987
14988 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14989 * -> tighten upper bound to x_v <= redlb[v]
14990 */
14991 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14993 redlb[v]);
14994 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14995 assert(!infeasible);
14996
14997 ub = SCIPvarGetUbGlobal(var);
14998 redub[v] = MIN(redub[v], ub);
14999 if( tightened )
15000 (*nchgbds)++;
15001 }
15002 }
15003 if( !SCIPisPositive(scip, obj) )
15004 {
15005 /* making the variable as large as possible does not increase the objective:
15006 * check if all up locks of the variables are due to linear constraints;
15007 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
15008 * constraints redundant is huge, we better do nothing for numerical reasons
15009 */
15011 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
15012 && !SCIPisHugeValue(scip, redub[v])
15013 && redub[v] > SCIPvarGetLbGlobal(var) )
15014 {
15015 SCIP_Real lb;
15016
15017 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
15018 * -> tighten lower bound to x_v >= redub[v]
15019 */
15020 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
15022 redub[v]);
15023 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15024 assert(!infeasible);
15025
15026 lb = SCIPvarGetLbGlobal(var);
15027 redlb[v] = MAX(redlb[v], lb);
15028 if( tightened )
15029 (*nchgbds)++;
15030 }
15031 }
15032 }
15033
15034 /* upgrade continuous variables to implicit integers */
15035 for( v = nintvars - nbinvars; v < nvars; ++v )
15036 {
15037 SCIP_VAR* var;
15038 SCIP_Bool infeasible;
15039
15040 var = vars[v];
15041 assert(var != NULL);
15042
15044 assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15045 assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15046 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15047
15048 /* we can only conclude implicit integrality if the variable appears in no other constraint */
15049 if( isimplint[v - nintvars + nbinvars]
15050 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15051 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15052 {
15053 /* since we locally copied the variable array we can change the variable type immediately */
15054 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15055 (*nchgvartypes)++;
15056 if( infeasible )
15057 {
15058 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15059 *cutoff = TRUE;
15060
15061 break;
15062 }
15063
15064 SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15066 }
15067 }
15068
15069 /* free temporary memory */
15070 SCIPfreeBufferArray(scip, &conscontvars);
15071 SCIPfreeBufferArray(scip, &isimplint);
15072 SCIPfreeBufferArray(scip, &nlocksup);
15073 SCIPfreeBufferArray(scip, &nlocksdown);
15074 SCIPfreeBufferArray(scip, &redub);
15075 SCIPfreeBufferArray(scip, &redlb);
15076
15077 SCIPfreeBufferArray(scip, &vars);
15078
15079 return SCIP_OKAY;
15080}
15081
15082/** helper function to enforce constraints */
15083static
15085 SCIP* scip, /**< SCIP data structure */
15086 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15087 SCIP_CONS** conss, /**< constraints to process */
15088 int nconss, /**< number of constraints */
15089 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15090 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15091 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15092 )
15093{
15094 SCIP_CONSHDLRDATA* conshdlrdata;
15095 SCIP_Bool checkrelmaxabs;
15096 SCIP_Bool violated;
15097 SCIP_Bool cutoff = FALSE;
15098 int c;
15099
15100 assert(scip != NULL);
15101 assert(conshdlr != NULL);
15102 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15103 assert(result != NULL);
15104
15105 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15106 assert(conshdlrdata != NULL);
15107
15108 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15109
15110 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15111
15112 /* check for violated constraints
15113 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15114 */
15115 *result = SCIP_FEASIBLE;
15116
15117 /* check all useful linear constraints for feasibility */
15118 for( c = 0; c < nusefulconss; ++c )
15119 {
15120 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15121
15122 if( violated )
15123 {
15124 /* insert LP row as cut */
15125 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15126 if ( cutoff )
15127 *result = SCIP_CUTOFF;
15128 else
15129 *result = SCIP_SEPARATED;
15130 }
15131 }
15132
15133 /* check all obsolete linear constraints for feasibility */
15134 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15135 {
15136 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15137
15138 if( violated )
15139 {
15140 /* insert LP row as cut */
15141 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15142 if ( cutoff )
15143 *result = SCIP_CUTOFF;
15144 else
15145 *result = SCIP_SEPARATED;
15146 }
15147 }
15148
15149 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15150
15151 return SCIP_OKAY;
15152}
15153
15154/** adds symmetry information of constraint to a symmetry detection graph */
15155static
15157 SCIP* scip, /**< SCIP pointer */
15158 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15159 SCIP_CONS* cons, /**< constraint */
15160 SYM_GRAPH* graph, /**< symmetry detection graph */
15161 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15162 )
15163{
15164 SCIP_CONSDATA* consdata;
15165 SCIP_VAR** vars;
15166 SCIP_Real* vals;
15167 SCIP_Real constant = 0.0;
15168 SCIP_Real lhs;
15169 SCIP_Real rhs;
15170 int nlocvars;
15171 int nvars;
15172 int i;
15173
15174 assert(scip != NULL);
15175 assert(cons != NULL);
15176 assert(graph != NULL);
15177 assert(success != NULL);
15178
15179 consdata = SCIPconsGetData(cons);
15180 assert(consdata != NULL);
15181
15182 /* get active variables of the constraint */
15183 nvars = SCIPgetNVars(scip);
15184 nlocvars = consdata->nvars;
15185
15186 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
15187 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
15188
15189 for( i = 0; i < nlocvars; ++i )
15190 {
15191 vars[i] = consdata->vars[i];
15192 vals[i] = consdata->vals[i];
15193 }
15194
15195 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15196 lhs = consdata->lhs - constant;
15197 rhs = consdata->rhs - constant;
15198
15199 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15200 * of the same constraint are rated as equal
15201 */
15202 if ( SCIPisInfinity(scip, rhs) )
15203 {
15204 SCIP_Real tmp;
15205 assert(!SCIPisInfinity(scip, -lhs));
15206
15207 for( i = 0; i < nlocvars; ++i )
15208 vals[i] *= -1;
15209 tmp = rhs;
15210 rhs = -lhs;
15211 lhs = -tmp;
15212 }
15213
15214 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
15215 cons, lhs, rhs, success) );
15216
15217 SCIPfreeBufferArray(scip, &vals);
15218 SCIPfreeBufferArray(scip, &vars);
15219
15220 return SCIP_OKAY;
15221}
15222
15223/*
15224 * Callback methods of constraint handler
15225 */
15226
15227/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15228static
15229SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15230{ /*lint --e{715}*/
15231 assert(scip != NULL);
15232 assert(conshdlr != NULL);
15233 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15234
15235 /* call inclusion method of constraint handler */
15237
15238 *valid = TRUE;
15239
15240 return SCIP_OKAY;
15241}
15242
15243/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15244static
15245SCIP_DECL_CONSFREE(consFreeLinear)
15246{ /*lint --e{715}*/
15247 SCIP_CONSHDLRDATA* conshdlrdata;
15248
15249 assert(scip != NULL);
15250 assert(conshdlr != NULL);
15251 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15252
15253 /* free constraint handler data */
15254 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15255 assert(conshdlrdata != NULL);
15256
15257 conshdlrdataFree(scip, &conshdlrdata);
15258
15259 SCIPconshdlrSetData(conshdlr, NULL);
15260
15261 return SCIP_OKAY;
15262}
15263
15264
15265/** initialization method of constraint handler (called after problem was transformed) */
15266static
15267SCIP_DECL_CONSINIT(consInitLinear)
15268{
15269 SCIP_CONSHDLRDATA* conshdlrdata;
15270 int c;
15271
15272 assert(scip != NULL);
15273
15274 /* check for event handler */
15275 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15276 assert(conshdlrdata != NULL);
15277 assert(conshdlrdata->eventhdlr != NULL);
15278 assert(nconss == 0 || conss != NULL);
15279
15280 conshdlrdata->naddconss = 0;
15281
15282 /* catch events for the constraints */
15283 for( c = 0; c < nconss; ++c )
15284 {
15285 /* catch all events */
15286 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15287 }
15288
15289 return SCIP_OKAY;
15290}
15291
15292
15293/** deinitialization method of constraint handler (called before transformed problem is freed) */
15294static
15295SCIP_DECL_CONSEXIT(consExitLinear)
15296{
15297 SCIP_CONSHDLRDATA* conshdlrdata;
15298 int c;
15299
15300 assert(scip != NULL);
15301
15302 /* check for event handler */
15303 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15304 assert(conshdlrdata != NULL);
15305 assert(conshdlrdata->eventhdlr != NULL);
15306
15307 /* drop events for the constraints */
15308 for( c = nconss - 1; c >= 0; --c )
15309 {
15310 SCIP_CONSDATA* consdata;
15311
15312 consdata = SCIPconsGetData(conss[c]);
15313 assert(consdata != NULL);
15314
15315 if( consdata->eventdata != NULL )
15316 {
15317 /* drop all events */
15318 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15319 assert(consdata->eventdata == NULL);
15320 }
15321 }
15322
15323 return SCIP_OKAY;
15324}
15325
15326/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15327static
15329 SCIP* scip, /**< SCIP data structure */
15330 SCIP_Real lhs, /**< left hand side */
15331 SCIP_Real rhs /**< right hand side */
15332 )
15333{
15334 assert(scip != NULL);
15335
15336 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15337}
15338
15339/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15340static
15342 SCIP* scip, /**< SCIP data structure */
15343 SCIP_Real x /**< value */
15344 )
15345{
15346 assert(scip != NULL);
15347
15348 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15349}
15350
15351/** performs linear constraint type classification as used for MIPLIB
15352 *
15353 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15354 *
15355 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15356 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15357 * Similarly, if specialized constraints were created through the API, these are currently not present.
15358 */
15360 SCIP* scip, /**< SCIP data structure */
15361 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15362 )
15363{
15364 int c;
15365 SCIP_CONSHDLR* conshdlr;
15366 SCIP_CONS** conss;
15367 int nconss;
15368
15369 assert(scip != NULL);
15370 assert(linconsstats != NULL);
15371 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15372 assert(conshdlr != NULL);
15373
15375 {
15376 conss = SCIPgetConss(scip);
15377 nconss = SCIPgetNConss(scip);
15378 }
15379 else
15380 {
15381 conss = SCIPconshdlrGetConss(conshdlr);
15382 nconss = SCIPconshdlrGetNConss(conshdlr);
15383 }
15384
15385 /* reset linear constraint type classification */
15386 SCIPlinConsStatsReset(linconsstats);
15387
15388 /* loop through all constraints */
15389 for( c = 0; c < nconss; c++ )
15390 {
15391 SCIP_CONS* cons;
15392 SCIP_CONSDATA* consdata;
15393 SCIP_Real lhs;
15394 SCIP_Real rhs;
15395 int i;
15396
15397 /* get constraint */
15398 cons = conss[c];
15399 assert(cons != NULL);
15400
15401 /* skip constraints that are not handled by the constraint handler */
15402 if( SCIPconsGetHdlr(cons) != conshdlr )
15403 continue;
15404
15405 /* get constraint data */
15406 consdata = SCIPconsGetData(cons);
15407 assert(consdata != NULL);
15408 rhs = consdata->rhs;
15409 lhs = consdata->lhs;
15410
15411 /* merge multiples and delete variables with zero coefficient */
15412 SCIP_CALL( mergeMultiples(scip, cons) );
15413 for( i = 0; i < consdata->nvars; i++ )
15414 {
15415 assert(!SCIPisZero(scip, consdata->vals[i]));
15416 }
15417
15418 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15419 if( consdata->nvars == 0 )
15420 {
15421 SCIPdebugMsg(scip, "classified as EMPTY: ");
15424
15425 continue;
15426 }
15427
15428 /* is constraint of type SCIP_CONSTYPE_FREE? */
15429 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15430 {
15431 SCIPdebugMsg(scip, "classified as FREE: ");
15434
15435 continue;
15436 }
15437
15438 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15439 if( consdata->nvars == 1 )
15440 {
15441 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15444
15445 continue;
15446 }
15447
15448 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15449 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15450 {
15451 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15454
15455 continue;
15456 }
15457
15458 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15459 if( consdata->nvars == 2 )
15460 {
15461 SCIP_LINCONSTYPE constype;
15462
15463 /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15464 if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15465 && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15466 {
15467 constype = SCIP_LINCONSTYPE_PRECEDENCE;
15468 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15469 }
15470 else
15471 {
15472 constype = SCIP_LINCONSTYPE_VARBOUND;
15473 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15474 }
15476
15477 SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15478
15479 continue;
15480 }
15481
15482 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15483 {
15484 SCIP_Real scale;
15485 SCIP_Real b;
15486 SCIP_Bool unmatched;
15487 int nnegbinvars;
15488
15489 unmatched = FALSE;
15490 nnegbinvars = 0;
15491
15492 scale = REALABS(consdata->vals[0]);
15493
15494 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15495 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15496 {
15497 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15498 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15499 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15500 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15501
15502 if( consdata->vals[i] < 0.0 )
15503 nnegbinvars++;
15504 }
15505
15506 if( !unmatched )
15507 {
15508 if( SCIPisEQ(scip, lhs, rhs) )
15509 {
15510 b = rhs/scale + nnegbinvars;
15511 if( SCIPisEQ(scip, 1.0, b) )
15512 {
15513 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15516
15517 continue;
15518 }
15519 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15520 {
15521 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15524
15525 continue;
15526 }
15527 }
15528
15529 /* compute right hand side divided by scale */
15530 if( !SCIPisInfinity(scip, rhs) )
15531 b = rhs/scale + nnegbinvars;
15532 else
15533 b = SCIPinfinity(scip);
15534
15535 if( SCIPisEQ(scip, 1.0, b) )
15536 {
15537 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15540
15541 /* relax right hand side to prevent further classifications */
15542 rhs = SCIPinfinity(scip);
15543 }
15544 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15545 {
15546 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15548
15550
15551 /* relax right hand side to prevent further classifications */
15552 rhs = SCIPinfinity(scip);
15553 }
15554
15555 if( !SCIPisInfinity(scip, lhs) )
15556 b = lhs/scale + nnegbinvars;
15557 else
15558 b = SCIPinfinity(scip);
15559
15560 if( SCIPisEQ(scip, 1.0, b) )
15561 {
15562 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15565
15566 /* relax left hand side to prevent further classifications */
15567 lhs = -SCIPinfinity(scip);
15568 }
15569
15570 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15571 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15572 continue;
15573 }
15574 }
15575
15576 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15577 /* @todo If coefficients or rhs are not integral, we currently do not check
15578 * if the constraint could be scaled (finitely), such that they are.
15579 */
15580 {
15581 SCIP_Real b;
15582 SCIP_Bool unmatched;
15583
15584 b = rhs;
15585 unmatched = FALSE;
15586 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15587 {
15588 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15589 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15590 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15591 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15592
15593 if( SCIPisNegative(scip, consdata->vals[i]) )
15594 b -= consdata->vals[i];
15595 }
15596 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15597
15598 if( !unmatched )
15599 {
15600 if( SCIPisEQ(scip, lhs, rhs) )
15601 {
15602 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15604
15606
15607 continue;
15608 }
15609 else
15610 {
15611 SCIP_Bool matched;
15612
15613 matched = FALSE;
15614 for( i = 0; i < consdata->nvars && !matched; i++ )
15615 {
15616 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15617 }
15618
15619 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15622 }
15623
15624 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15625 if( SCIPisInfinity(scip, -lhs) )
15626 continue;
15627 else
15628 rhs = SCIPinfinity(scip);
15629 }
15630 }
15631
15632 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15633 {
15634 SCIP_Real b;
15635 SCIP_Bool unmatched;
15636
15637 unmatched = FALSE;
15638
15639 b = rhs;
15640 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15641
15642 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15643 {
15644 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15645 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15646 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15647 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15648 }
15649
15650 if( !unmatched )
15651 {
15652 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15655
15656 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15657 if( SCIPisInfinity(scip, -lhs) )
15658 continue;
15659 else
15660 rhs = SCIPinfinity(scip);
15661 }
15662 }
15663
15664 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15665 {
15666 SCIP_Bool unmatched;
15667
15668 unmatched = FALSE;
15669 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15670 {
15671 if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15672 && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15673 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15674 unmatched = TRUE;
15675 }
15676
15677 if( !unmatched )
15678 {
15679 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15682
15683 continue;
15684 }
15685 }
15686
15687 /* no special structure detected */
15688 SCIPdebugMsg(scip, "classified as GENERAL: ");
15690 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15691 }
15692
15693 return SCIP_OKAY;
15694}
15695
15696
15697/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15698static
15699SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15700{ /*lint --e{715}*/
15701 int c;
15702#ifdef SCIP_STATISTIC
15703 SCIP_CONSHDLRDATA* conshdlrdata;
15704 int ngoodconss;
15705 int nallconss;
15706#endif
15707
15708 /* delete all linear constraints that were upgraded to a more specific constraint type;
15709 * make sure, only active variables remain in the remaining constraints
15710 */
15711 assert(scip != NULL);
15712
15713#ifdef SCIP_STATISTIC
15714 /* count number of well behaved linear constraints */
15715 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15716 assert(conshdlrdata != NULL);
15717
15718 ngoodconss = 0;
15719 nallconss = 0;
15720
15721 for( c = 0; c < nconss; ++c )
15722 {
15723 SCIP_CONSDATA* consdata;
15724
15725 if( SCIPconsIsDeleted(conss[c]) )
15726 continue;
15727
15728 consdata = SCIPconsGetData(conss[c]);
15729 assert(consdata != NULL);
15730
15731 if( consdata->upgraded )
15732 continue;
15733
15734 nallconss++;
15735
15737
15738 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15739 ngoodconss++;
15740 }
15741 if( nallconss )
15742 {
15743 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15744 }
15745#endif
15746
15747 for( c = 0; c < nconss; ++c )
15748 {
15749 SCIP_CONSDATA* consdata;
15750
15751 if( SCIPconsIsDeleted(conss[c]) )
15752 continue;
15753
15754 consdata = SCIPconsGetData(conss[c]);
15755 assert(consdata != NULL);
15756
15757 if( consdata->upgraded )
15758 {
15759 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15760 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15761 */
15762 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15763 }
15764 else
15765 {
15766 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15767 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15768 }
15769 }
15770
15771 return SCIP_OKAY;
15772}
15773
15774/** solving process initialization method of constraint handler */
15775static
15776SCIP_DECL_CONSINITSOL(consInitsolLinear)
15777{ /*lint --e{715}*/
15778 /* add nlrow representation to NLP, if NLP had been constructed */
15780 {
15781 int c;
15782 for( c = 0; c < nconss; ++c )
15783 {
15784 SCIP_CALL( addNlrow(scip, conss[c]) );
15785 }
15786 }
15787
15788 return SCIP_OKAY;
15789}
15790
15791/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15792static
15793SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15794{ /*lint --e{715}*/
15795 int c;
15796
15797 assert(scip != NULL);
15798
15799 /* release the rows and nlrows of all constraints */
15800 for( c = 0; c < nconss; ++c )
15801 {
15802 SCIP_CONSDATA* consdata;
15803
15804 consdata = SCIPconsGetData(conss[c]);
15805 assert(consdata != NULL);
15806
15807 if( consdata->row != NULL )
15808 {
15809 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15810 }
15811
15812 if( consdata->nlrow != NULL )
15813 {
15814 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15815 }
15816 }
15817
15818 /* if this is a restart, convert cutpool rows into linear constraints */
15819 if( restart )
15820 {
15821 int ncutsadded;
15822
15823 ncutsadded = 0;
15824
15825 /* create out of all active cuts in cutpool linear constraints */
15826 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15827
15828 if( ncutsadded > 0 )
15829 {
15831 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15832 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15833 * line correctly
15834 */
15836 }
15837 }
15838
15839 return SCIP_OKAY;
15840}
15841
15842
15843/** constraint activation notification method of constraint handler */
15844static
15845SCIP_DECL_CONSACTIVE(consActiveLinear)
15846{ /*lint --e{715}*/
15847 assert(cons != NULL);
15848
15850 {
15851 SCIP_CALL( addNlrow(scip, cons) );
15852 }
15853
15854 return SCIP_OKAY;
15855}
15856
15857/** constraint deactivation notification method of constraint handler */
15858static
15859SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15860{ /*lint --e{715}*/
15861 SCIP_CONSDATA* consdata;
15862
15863 assert(scip != NULL);
15864 assert(conshdlr != NULL);
15865 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15866 assert(cons != NULL );
15867
15868 /* get constraint data */
15869 consdata = SCIPconsGetData(cons);
15870 assert(consdata != NULL);
15871
15872 if( SCIPconsIsDeleted(cons) )
15873 {
15874 SCIP_CONSHDLRDATA* conshdlrdata;
15875
15876 /* check for event handler */
15877 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15878 assert(conshdlrdata != NULL);
15879 assert(conshdlrdata->eventhdlr != NULL);
15880
15881 /* free event data */
15882 if( consdata->eventdata != NULL )
15883 {
15884 /* drop bound change events of variables */
15885 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15886 }
15887 assert(consdata->eventdata == NULL);
15888 }
15889
15890 /* remove row from NLP, if still in solving
15891 * if we are in exitsolve, the whole NLP will be freed anyway
15892 */
15893 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15894 {
15895 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15896 }
15897
15898 return SCIP_OKAY;
15899}
15900
15901
15902/** frees specific constraint data */
15903static
15904SCIP_DECL_CONSDELETE(consDeleteLinear)
15905{ /*lint --e{715}*/
15906 assert(scip != NULL);
15907 assert(conshdlr != NULL);
15908 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15909
15910 if( (*consdata)->eventdata != NULL )
15911 {
15912 SCIP_CONSHDLRDATA* conshdlrdata;
15913
15914 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15915 assert(conshdlrdata != NULL);
15916
15917 /* drop all events */
15918 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15919 assert((*consdata)->eventdata == NULL);
15920 }
15921
15922 /* free linear constraint */
15923 SCIP_CALL( consdataFree(scip, consdata) );
15924
15925 return SCIP_OKAY;
15926}
15927
15928
15929/** transforms constraint data into data belonging to the transformed problem */
15930static
15931SCIP_DECL_CONSTRANS(consTransLinear)
15932{ /*lint --e{715}*/
15933 SCIP_CONSDATA* sourcedata;
15934 SCIP_CONSDATA* targetdata;
15935
15936 /*debugMsg(scip, "Trans method of linear constraints\n");*/
15937
15938 assert(scip != NULL);
15939 assert(conshdlr != NULL);
15940 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15942 assert(sourcecons != NULL);
15943 assert(targetcons != NULL);
15944
15945 sourcedata = SCIPconsGetData(sourcecons);
15946 assert(sourcedata != NULL);
15947 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15948
15949 /* create linear constraint data for target constraint */
15950 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15951
15952#ifndef NDEBUG
15953 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15954 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15955 {
15956 int n;
15957 for(n = targetdata->nvars - 1; n >= 0; --n )
15958 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15959 }
15960#endif
15961
15962 /* create target constraint */
15963 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15964 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15965 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15966 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15967 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15968
15969 return SCIP_OKAY;
15970}
15971
15972
15973/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15974static
15975SCIP_DECL_CONSINITLP(consInitlpLinear)
15976{ /*lint --e{715}*/
15977 int c;
15978
15979 assert(scip != NULL);
15980 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15981
15982 *infeasible = FALSE;
15983
15984 for( c = 0; c < nconss && !(*infeasible); ++c )
15985 {
15986 assert(SCIPconsIsInitial(conss[c]));
15987 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15988 }
15989
15990 return SCIP_OKAY;
15991}
15992
15993
15994/** separation method of constraint handler for LP solutions */
15995static
15996SCIP_DECL_CONSSEPALP(consSepalpLinear)
15997{ /*lint --e{715}*/
15998 SCIP_CONSHDLRDATA* conshdlrdata;
15999 SCIP_Real loclowerbound;
16000 SCIP_Real glblowerbound;
16001 SCIP_Real cutoffbound;
16002 SCIP_Real maxbound;
16003 SCIP_Bool separatecards;
16004 SCIP_Bool cutoff;
16005 int c;
16006 int depth;
16007 int nrounds;
16008 int maxsepacuts;
16009 int ncuts;
16010
16011 assert(scip != NULL);
16012 assert(conshdlr != NULL);
16013 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16014 assert(result != NULL);
16015
16016 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16017 assert(conshdlrdata != NULL);
16018 depth = SCIPgetDepth(scip);
16019 nrounds = SCIPgetNSepaRounds(scip);
16020
16021 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16022
16023 *result = SCIP_DIDNOTRUN;
16024
16025 /* only call the separator a given number of times at each node */
16026 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16027 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16028 return SCIP_OKAY;
16029
16030 /* get the maximal number of cuts allowed in a separation round */
16031 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16032
16033 /* check if we want to produce knapsack cardinality cuts at this node */
16034 loclowerbound = SCIPgetLocalLowerbound(scip);
16035 glblowerbound = SCIPgetLowerbound(scip);
16036 cutoffbound = SCIPgetCutoffbound(scip);
16037 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16038 separatecards = SCIPisLE(scip, loclowerbound, maxbound);
16039 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
16040
16041 *result = SCIP_DIDNOTFIND;
16042 ncuts = 0;
16043 cutoff = FALSE;
16044
16045 /* check all useful linear constraints for feasibility */
16046 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16047 {
16048 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16049 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16050 }
16051
16052 /* adjust return value */
16053 if( cutoff )
16054 *result = SCIP_CUTOFF;
16055 else if( ncuts > 0 )
16056 *result = SCIP_SEPARATED;
16057
16058 /* combine linear constraints to get more cuts */
16059 /**@todo further cuts of linear constraints */
16060
16061 return SCIP_OKAY;
16062}
16063
16064
16065/** separation method of constraint handler for arbitrary primal solutions */
16066static
16067SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16068{ /*lint --e{715}*/
16069 SCIP_CONSHDLRDATA* conshdlrdata;
16070 int c;
16071 int depth;
16072 int nrounds;
16073 int maxsepacuts;
16074 int ncuts;
16075 SCIP_Bool cutoff;
16076
16077 assert(scip != NULL);
16078 assert(conshdlr != NULL);
16079 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16080 assert(result != NULL);
16081
16082 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16083 assert(conshdlrdata != NULL);
16084 depth = SCIPgetDepth(scip);
16085 nrounds = SCIPgetNSepaRounds(scip);
16086
16087 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16088
16089 *result = SCIP_DIDNOTRUN;
16090
16091 /* only call the separator a given number of times at each node */
16092 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16093 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16094 return SCIP_OKAY;
16095
16096 /* get the maximal number of cuts allowed in a separation round */
16097 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16098
16099 *result = SCIP_DIDNOTFIND;
16100 ncuts = 0;
16101 cutoff = FALSE;
16102
16103 /* check all useful linear constraints for feasibility */
16104 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16105 {
16106 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16107 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16108 }
16109
16110 /* adjust return value */
16111 if( cutoff )
16112 *result = SCIP_CUTOFF;
16113 else if( ncuts > 0 )
16114 *result = SCIP_SEPARATED;
16115
16116 /* combine linear constraints to get more cuts */
16117 /**@todo further cuts of linear constraints */
16118
16119 return SCIP_OKAY;
16120}
16121
16122
16123/** constraint enforcing method of constraint handler for LP solutions */
16124static
16125SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16126{ /*lint --e{715}*/
16127 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16128
16129 return SCIP_OKAY;
16130}
16131
16132/** constraint enforcing method of constraint handler for relaxation solutions */
16133static
16134SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16135{ /*lint --e{715}*/
16136 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16137
16138 return SCIP_OKAY;
16139}
16140
16141/** constraint enforcing method of constraint handler for pseudo solutions */
16142static
16143SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16144{ /*lint --e{715}*/
16145 SCIP_CONSHDLRDATA* conshdlrdata;
16146 SCIP_Bool checkrelmaxabs;
16147 SCIP_Bool violated;
16148 int c;
16149
16150 assert(scip != NULL);
16151 assert(conshdlr != NULL);
16152 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16153 assert(result != NULL);
16154
16155 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16156 assert(conshdlrdata != NULL);
16157
16158 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16159
16160 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16161
16162 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16163 if( objinfeasible )
16164 {
16165 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16166
16167 *result = SCIP_DIDNOTRUN;
16168 return SCIP_OKAY;
16169 }
16170
16171 /* check all linear constraints for feasibility */
16172 violated = FALSE;
16173 for( c = 0; c < nconss && !violated; ++c )
16174 {
16175 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16176 }
16177
16178 if( violated )
16179 *result = SCIP_INFEASIBLE;
16180 else
16181 *result = SCIP_FEASIBLE;
16182
16183 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16184
16185 return SCIP_OKAY;
16186}
16187
16188
16189/** feasibility check method of constraint handler for integral solutions */
16190static
16191SCIP_DECL_CONSCHECK(consCheckLinear)
16192{ /*lint --e{715}*/
16193 SCIP_CONSHDLRDATA* conshdlrdata;
16194 SCIP_Bool checkrelmaxabs;
16195 int c;
16196
16197 assert(scip != NULL);
16198 assert(conshdlr != NULL);
16199 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16200 assert(result != NULL);
16201
16202 *result = SCIP_FEASIBLE;
16203
16204 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16205 assert(conshdlrdata != NULL);
16206
16207 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16208
16209 /*debugMsg(scip, "Check method of linear constraints\n");*/
16210
16211 /* check all linear constraints for feasibility */
16212 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16213 {
16214 SCIP_Bool violated = FALSE;
16215 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16216
16217 if( violated )
16218 {
16219 *result = SCIP_INFEASIBLE;
16220
16221 if( printreason )
16222 {
16223 SCIP_CONSDATA* consdata;
16224 SCIP_Real activity;
16225
16226 consdata = SCIPconsGetData(conss[c]);
16227 assert( consdata != NULL);
16228
16229 activity = consdataGetActivity(scip, consdata, sol);
16230
16231 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16232 SCIPinfoMessage(scip, NULL, ";\n");
16233
16234 if( activity == SCIP_INVALID ) /*lint !e777*/
16235 SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16236 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16237 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16238 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16239 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16240 }
16241 }
16242 }
16243
16244 return SCIP_OKAY;
16245}
16246
16247
16248/** domain propagation method of constraint handler */
16249static
16250SCIP_DECL_CONSPROP(consPropLinear)
16251{ /*lint --e{715}*/
16252 SCIP_CONSHDLRDATA* conshdlrdata;
16253 SCIP_Bool rangedrowpropagation = FALSE;
16254 SCIP_Bool tightenbounds;
16255 SCIP_Bool cutoff;
16256
16257 int nchgbds;
16258 int i;
16259
16260 assert(scip != NULL);
16261 assert(conshdlr != NULL);
16262 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16263 assert(result != NULL);
16264
16265 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16266 assert(conshdlrdata != NULL);
16267
16268 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16269
16270 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16271 if( SCIPinProbing(scip) )
16272 tightenbounds = TRUE;
16273 else
16274 {
16275 int depth;
16276 int propfreq;
16277 int tightenboundsfreq;
16278 int rangedrowfreq;
16279
16280 depth = SCIPgetDepth(scip);
16281 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16282 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16283 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16284 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16285
16286 /* check if we want to do ranged row propagation */
16287 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16288 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16289 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16290 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16291 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16292 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16293 }
16294
16295 cutoff = FALSE;
16296 nchgbds = 0;
16297
16298 /* process constraints marked for propagation */
16299 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16300 {
16302 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16303 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16304 }
16305
16306 /* adjust result code */
16307 if( cutoff )
16308 *result = SCIP_CUTOFF;
16309 else if( nchgbds > 0 )
16310 *result = SCIP_REDUCEDDOM;
16311 else
16312 *result = SCIP_DIDNOTFIND;
16313
16314 return SCIP_OKAY;
16315}
16316
16317
16318#define MAXCONSPRESOLROUNDS 10
16319/** presolving method of constraint handler */
16320static
16321SCIP_DECL_CONSPRESOL(consPresolLinear)
16322{ /*lint --e{715}*/
16323 SCIP_CONSHDLRDATA* conshdlrdata;
16324 SCIP_CONS* cons;
16325 SCIP_CONSDATA* consdata;
16326 SCIP_Real minactivity;
16327 SCIP_Real maxactivity;
16328 SCIP_Bool isminacttight;
16329 SCIP_Bool ismaxacttight;
16330 SCIP_Bool isminsettoinfinity;
16331 SCIP_Bool ismaxsettoinfinity;
16332 SCIP_Bool cutoff;
16333 int oldnfixedvars;
16334 int oldnaggrvars;
16335 int oldnchgbds;
16336 int oldndelconss;
16337 int oldnupgdconss;
16338 int oldnchgcoefs;
16339 int oldnchgsides;
16340 int firstchange;
16341 int firstupgradetry;
16342 int c;
16343
16344 assert(scip != NULL);
16345 assert(conshdlr != NULL);
16346 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16347 assert(result != NULL);
16348
16349 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16350
16351 /* remember old preprocessing counters */
16352 cutoff = FALSE;
16353 oldnfixedvars = *nfixedvars;
16354 oldnaggrvars = *naggrvars;
16355 oldnchgbds = *nchgbds;
16356 oldndelconss = *ndelconss;
16357 oldnupgdconss = *nupgdconss;
16358 oldnchgcoefs = *nchgcoefs;
16359 oldnchgsides = *nchgsides;
16360
16361 /* get constraint handler data */
16362 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16363 assert(conshdlrdata != NULL);
16364
16365 /* process single constraints */
16366 firstchange = INT_MAX;
16367 firstupgradetry = INT_MAX;
16368 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16369 {
16370 int npresolrounds;
16371 SCIP_Bool infeasible;
16372
16373 infeasible = FALSE;
16374
16375 cons = conss[c];
16376 assert(SCIPconsIsActive(cons));
16377 consdata = SCIPconsGetData(cons);
16378 assert(consdata != NULL);
16379
16380 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16381 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16382 {
16383 consdata->lhs = consdata->rhs;
16384 assert(consdata->row == NULL);
16385 }
16386
16387 if( consdata->eventdata == NULL )
16388 {
16389 /* catch bound change events of variables */
16390 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16391 assert(consdata->eventdata != NULL);
16392 }
16393
16394 /* constraint should not be already presolved in the initial round */
16395 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16396 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16397 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16398 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16399
16400 /* incorporate fixings and aggregations in constraint */
16401 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16402
16403 if( infeasible )
16404 {
16405 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16406 cutoff = TRUE;
16407 break;
16408 }
16409
16410 assert(consdata->removedfixings);
16411
16412 /* we can only presolve linear constraints, that are not modifiable */
16413 if( SCIPconsIsModifiable(cons) )
16414 continue;
16415
16416 /* remember the first changed constraint to begin the next aggregation round with */
16417 if( firstchange == INT_MAX && consdata->changed )
16418 firstchange = c;
16419
16420 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16421 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16422 firstupgradetry = c;
16423
16424 /* check, if constraint is already preprocessed */
16425 if( consdata->presolved )
16426 continue;
16427
16428 assert(SCIPconsIsActive(cons));
16429
16430 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16432
16433 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16434 * to avoid nearly infinite cycling due to very small bound changes)
16435 */
16436 npresolrounds = 0;
16437 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16438 {
16439 assert(!cutoff);
16440 npresolrounds++;
16441
16442 /* mark constraint being presolved and propagated */
16443 consdata->presolved = TRUE;
16445
16446 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16447
16448 if( infeasible )
16449 {
16450 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16451 cutoff = TRUE;
16452 break;
16453 }
16454
16455 /* tighten left and right hand side due to integrality */
16456 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16457
16458 if( infeasible )
16459 {
16460 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16461 cutoff = TRUE;
16462 break;
16463 }
16464
16465 /* check bounds */
16466 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16467 {
16468 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16469 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16470 cutoff = TRUE;
16471 break;
16472 }
16473
16474 /* tighten variable's bounds */
16475 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16476 if( cutoff )
16477 break;
16478
16479 /* check for fixed variables */
16480 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16481 if( cutoff )
16482 break;
16483
16484 /* check constraint for infeasibility and redundancy */
16485 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
16486 &isminsettoinfinity, &ismaxsettoinfinity);
16487 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16488 {
16489 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16490 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16491 cutoff = TRUE;
16492 break;
16493 }
16494 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16495 {
16496 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16497 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16498 SCIP_CALL( SCIPdelCons(scip, cons) );
16499 assert(!SCIPconsIsActive(cons));
16500
16501 if( !consdata->upgraded )
16502 (*ndelconss)++;
16503 break;
16504 }
16505 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16506 {
16507 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16508 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16509 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16510 if( !consdata->upgraded )
16511 (*nchgsides)++;
16512 }
16513 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16514 {
16515 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16516 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16518 if( !consdata->upgraded )
16519 (*nchgsides)++;
16520 }
16521
16522 /* handle empty constraint */
16523 if( consdata->nvars == 0 )
16524 {
16525 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16526 {
16527 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16528 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16529 cutoff = TRUE;
16530 }
16531 else
16532 {
16533 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16534 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16535 SCIP_CALL( SCIPdelCons(scip, cons) );
16536 assert(!SCIPconsIsActive(cons));
16537
16538 if( !consdata->upgraded )
16539 (*ndelconss)++;
16540 }
16541 break;
16542 }
16543
16544 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16545 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16546
16547 /* try to simplify inequalities */
16548 if( conshdlrdata->simplifyinequalities )
16549 {
16550 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16551
16552 if( cutoff )
16553 break;
16554 }
16555
16556 /* aggregation variable in equations */
16557 if( conshdlrdata->aggregatevariables )
16558 {
16559 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16560 if( cutoff )
16561 break;
16562 }
16563 }
16564
16565 if( !cutoff && !SCIPisStopped(scip) )
16566 {
16567 /* perform ranged row propagation */
16568 if( conshdlrdata->rangedrowpropagation )
16569 {
16570 int lastnfixedvars;
16571
16572 lastnfixedvars = *nfixedvars;
16573
16574 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16575 if( !cutoff )
16576 {
16577 if( lastnfixedvars < *nfixedvars )
16578 {
16579 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16580 }
16581 }
16582 }
16583
16584 /* extract cliques from constraint */
16585 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16586 {
16587 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16588 nfixedvars, nchgbds, &cutoff) );
16589
16590 /* check if the constraint got redundant or infeasible */
16591 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16592 {
16593 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16594 {
16595 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16596 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16597 cutoff = TRUE;
16598 }
16599 else
16600 {
16601 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16602 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16603 SCIP_CALL( SCIPdelCons(scip, cons) );
16604 assert(!SCIPconsIsActive(cons));
16605
16606 if( !consdata->upgraded )
16607 (*ndelconss)++;
16608 }
16609 }
16610 }
16611
16612 /* convert special equalities */
16613 if( !cutoff && SCIPconsIsActive(cons) )
16614 {
16615 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16616 }
16617
16618 /* apply dual presolving for variables that appear in only one constraint */
16619 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16620 {
16621 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16622 }
16623
16624 /* check if an inequality is parallel to the objective function */
16625 if( !cutoff && SCIPconsIsActive(cons) )
16626 {
16627 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16628 }
16629
16630 /* remember the first changed constraint to begin the next aggregation round with */
16631 if( firstchange == INT_MAX && consdata->changed )
16632 firstchange = c;
16633
16634 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16635 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16636 firstupgradetry = c;
16637 }
16638
16639 /* singleton column stuffing */
16640 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16641 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16642 {
16643 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16644 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16645
16646 /* handle empty constraint */
16647 if( consdata->nvars == 0 )
16648 {
16649 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16650 {
16651 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16652 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16653 cutoff = TRUE;
16654 }
16655 else
16656 {
16657 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16658 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16659 SCIP_CALL( SCIPdelCons(scip, cons) );
16660 assert(!SCIPconsIsActive(cons));
16661
16662 if( !consdata->upgraded )
16663 (*ndelconss)++;
16664 }
16665 break;
16666 }
16667 }
16668 }
16669
16670 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16671 * only apply this expensive procedure in exhaustive presolving timing
16672 */
16673 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16674 {
16675 assert(firstchange >= 0);
16676
16677 if( firstchange < nconss && conshdlrdata->presolusehashing )
16678 {
16679 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16680 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16681 ndelconss, nchgsides) );
16682 }
16683
16684 if( firstchange < nconss && conshdlrdata->presolpairwise )
16685 {
16686 SCIP_CONS** usefulconss;
16687 int nusefulconss;
16688 int firstchangenew;
16689 SCIP_Longint npaircomparisons;
16690
16691 npaircomparisons = 0;
16692 oldndelconss = *ndelconss;
16693 oldnchgsides = *nchgsides;
16694 oldnchgcoefs = *nchgcoefs;
16695
16696 /* allocate temporary memory */
16697 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16698
16699 nusefulconss = 0;
16700 firstchangenew = -1;
16701 for( c = 0; c < nconss; ++c )
16702 {
16703 /* update firstchange */
16704 if( c == firstchange )
16705 firstchangenew = nusefulconss;
16706
16707 /* ignore inactive and modifiable constraints */
16708 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16709 continue;
16710
16711 usefulconss[nusefulconss] = conss[c];
16712 ++nusefulconss;
16713 }
16714 firstchange = firstchangenew;
16715 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16716
16717 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16718 {
16719 /* constraint has become inactive or modifiable during pairwise presolving */
16720 if( usefulconss[c] == NULL )
16721 continue;
16722
16723 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16724
16725 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16726 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16727 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16728
16729 if( npaircomparisons > conshdlrdata->nmincomparisons )
16730 {
16731 assert(npaircomparisons > 0);
16732 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16733 break;
16734 oldndelconss = *ndelconss;
16735 oldnchgsides = *nchgsides;
16736 oldnchgcoefs = *nchgcoefs;
16737 npaircomparisons = 0;
16738 }
16739 }
16740 /* free temporary memory */
16741 SCIPfreeBufferArray(scip, &usefulconss);
16742 }
16743 }
16744
16745 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16746 * in linear constraints and we therefore have full information about it
16747 */
16748 if( !cutoff && firstupgradetry < nconss
16749 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16750 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16751 )
16752 {
16753 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16754 {
16755 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds, nchgvartypes) );
16756 }
16757 }
16758
16759 /* try to upgrade constraints into a more specific constraint type;
16760 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16761 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16762 */
16763 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16764 {
16765 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16766 {
16767 cons = conss[c];
16768
16769 /* don't upgrade modifiable constraints */
16770 if( SCIPconsIsModifiable(cons) )
16771 continue;
16772
16773 consdata = SCIPconsGetData(cons);
16774 assert(consdata != NULL);
16775
16776 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16777 if( consdata->upgradetried )
16778 continue;
16779 /* @todo force that upgrade will be performed later? */
16780 if( !consdata->presolved )
16781 continue;
16782
16783 consdata->upgradetried = TRUE;
16784 if( SCIPconsIsActive(cons) )
16785 {
16786 SCIP_CONS* upgdcons;
16787
16788 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16789 if( upgdcons != NULL )
16790 {
16791 /* add the upgraded constraint to the problem */
16792 SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16793 SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16794 (*nupgdconss)++;
16795
16796 /* mark the linear constraint being upgraded and to be removed after presolving;
16797 * don't delete it directly, because it may help to preprocess other linear constraints
16798 */
16799 assert(!consdata->upgraded);
16800 consdata->upgraded = TRUE;
16801
16802 /* delete upgraded inequalities immediately;
16803 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16804 */
16805 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16806 || !conshdlrdata->presolpairwise
16807 || (conshdlrdata->maxaggrnormscale == 0.0) )
16808 {
16809 SCIP_CALL( SCIPdelCons(scip, cons) );
16810 }
16811 }
16812 }
16813 }
16814 }
16815
16816 /* return the correct result code */
16817 if( cutoff )
16818 *result = SCIP_CUTOFF;
16819 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16820 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16821 *result = SCIP_SUCCESS;
16822 else
16823 *result = SCIP_DIDNOTFIND;
16824
16825 return SCIP_OKAY;
16826}
16827
16828
16829/** propagation conflict resolving method of constraint handler */
16830static
16831SCIP_DECL_CONSRESPROP(consRespropLinear)
16832{ /*lint --e{715}*/
16833 assert(scip != NULL);
16834 assert(cons != NULL);
16835 assert(result != NULL);
16836
16837 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16838
16839 return SCIP_OKAY;
16840}
16841
16842
16843/** variable rounding lock method of constraint handler */
16844static
16845SCIP_DECL_CONSLOCK(consLockLinear)
16846{ /*lint --e{715}*/
16847 SCIP_CONSDATA* consdata;
16848 SCIP_Bool haslhs;
16849 SCIP_Bool hasrhs;
16850 int i;
16851
16852 assert(scip != NULL);
16853 assert(cons != NULL);
16854 consdata = SCIPconsGetData(cons);
16855 assert(consdata != NULL);
16856
16857 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16858 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16859
16860 /* update rounding locks of every single variable */
16861 for( i = 0; i < consdata->nvars; ++i )
16862 {
16863 if( SCIPisPositive(scip, consdata->vals[i]) )
16864 {
16865 if( haslhs )
16866 {
16867 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16868 }
16869 if( hasrhs )
16870 {
16871 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16872 }
16873 }
16874 else
16875 {
16876 if( haslhs )
16877 {
16878 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16879 }
16880 if( hasrhs )
16881 {
16882 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16883 }
16884 }
16885 }
16886
16887 return SCIP_OKAY;
16888}
16889
16890
16891/** variable deletion method of constraint handler */
16892static
16893SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16894{
16895 assert(scip != NULL);
16896 assert(conshdlr != NULL);
16897 assert(conss != NULL || nconss == 0);
16898
16899 if( nconss > 0 )
16900 {
16901 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16902 }
16903
16904 return SCIP_OKAY;
16905}
16906
16907/** constraint display method of constraint handler */
16908static
16909SCIP_DECL_CONSPRINT(consPrintLinear)
16910{ /*lint --e{715}*/
16911 assert(scip != NULL);
16912 assert(conshdlr != NULL);
16913 assert(cons != NULL);
16914
16916
16917 return SCIP_OKAY;
16918}
16919
16920/** constraint copying method of constraint handler */
16921static
16922SCIP_DECL_CONSCOPY(consCopyLinear)
16923{ /*lint --e{715}*/
16924 SCIP_VAR** sourcevars;
16925 SCIP_Real* sourcecoefs;
16926 const char* consname;
16927 int nvars;
16928
16929 assert(scip != NULL);
16930 assert(sourcescip != NULL);
16931 assert(sourcecons != NULL);
16932
16933 /* get variables and coefficients of the source constraint */
16934 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16935 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16936 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16937
16938 if( name != NULL )
16939 consname = name;
16940 else
16941 consname = SCIPconsGetName(sourcecons);
16942
16943 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16944 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16945 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16946 assert(cons != NULL || *valid == FALSE);
16947
16948 /* @todo should also the checkabsolute flag of the constraint be copied? */
16949
16950 return SCIP_OKAY;
16951}
16952
16953/** find operators '<=', '==', '>=', [free] in input string and return those places
16954 *
16955 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16956 */
16957static
16959 const char* str, /**< null terminated input string */
16960 char** firstoperator, /**< pointer to store the string starting at the first operator */
16961 char** secondoperator, /**< pointer to store the string starting at the second operator */
16962 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16963 )
16964{
16965 char* curr;
16966
16967 assert(str != NULL);
16968 assert(firstoperator != NULL);
16969 assert(secondoperator != NULL);
16970
16971 *firstoperator = NULL;
16972 *secondoperator = NULL;
16973
16974 curr = (char*)str;
16975 *success = TRUE;
16976
16977 /* loop over the input string to find all operators */
16978 while( *curr && *success )
16979 {
16980 SCIP_Bool found = FALSE;
16981 int increment = 1;
16982
16983 /* try if we found a possible operator */
16984 switch( *curr )
16985 {
16986 case '<':
16987 case '=':
16988 case '>':
16989
16990 /* check if the two characters curr[0,1] form an operator together */
16991 if( curr[1] == '=' )
16992 {
16993 found = TRUE;
16994
16995 /* update increment to continue after this operator */
16996 increment = 2;
16997 }
16998 break;
16999 case '[':
17000 if( strncmp(curr, "[free]", 6) == 0 )
17001 {
17002 found = TRUE;
17003
17004 /* update increment to continue after this operator */
17005 increment = 6;
17006 }
17007 break;
17008 default:
17009 break;
17010 }
17011
17012 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
17013 if( found )
17014 {
17015 if( *firstoperator == NULL )
17016 {
17017 *firstoperator = curr;
17018 }
17019 else
17020 {
17021 if( *secondoperator != NULL )
17022 {
17023 SCIPerrorMessage("Found more than two operators in line %s\n", str);
17024 *success = FALSE;
17025 }
17026 else if( strncmp(*firstoperator, "<=", 2) != 0 )
17027 {
17028 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17029 *success = FALSE;
17030 }
17031 else if( strncmp(curr, "<=", 2) != 0 )
17032 {
17033 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17034 *success = FALSE;
17035 }
17036
17037 *secondoperator = curr;
17038 }
17039 }
17040
17041 curr += increment;
17042 }
17043
17044 /* check if we did find at least one operator */
17045 if( *success )
17046 {
17047 if( *firstoperator == NULL )
17048 {
17049 SCIPerrorMessage("Could not find any operator in line %s\n", str);
17050 *success = FALSE;
17051 }
17052 }
17053}
17054
17055/** constraint parsing method of constraint handler */
17056static
17057SCIP_DECL_CONSPARSE(consParseLinear)
17058{ /*lint --e{715}*/
17059 SCIP_VAR** vars;
17060 SCIP_Real* coefs;
17061 int nvars;
17062 int coefssize;
17063 int requsize;
17064 SCIP_Real lhs;
17065 SCIP_Real rhs;
17066 char* endptr;
17067 char* firstop;
17068 char* secondop;
17069 SCIP_Bool operatorsuccess;
17070 char* lhsstrptr;
17071 char* rhsstrptr;
17072 char* varstrptr;
17073
17074 assert(scip != NULL);
17075 assert(success != NULL);
17076 assert(str != NULL);
17077 assert(name != NULL);
17078 assert(cons != NULL);
17079
17080 /* set left and right hand side to their default values */
17081 lhs = -SCIPinfinity(scip);
17082 rhs = SCIPinfinity(scip);
17083
17084 (*success) = FALSE;
17085
17086 /* return of string empty */
17087 if( !*str )
17088 return SCIP_OKAY;
17089
17090 /* ignore whitespace */
17091 SCIP_CALL( SCIPskipSpace((char**)&str) );
17092
17093 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17094 * and the special word [free]
17095 */
17096 findOperators(str, &firstop, &secondop, &operatorsuccess);
17097
17098 /* if the grammar is not valid for parsing a linear constraint, return */
17099 if( ! operatorsuccess )
17100 return SCIP_OKAY;
17101
17102 varstrptr = (char *)str;
17103 lhsstrptr = rhsstrptr = NULL;
17104 assert(firstop != NULL);
17105
17106 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17107 switch( *firstop )
17108 {
17109 case '<':
17110 assert(firstop[1] == '=');
17111 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17112 if( secondop != NULL )
17113 {
17114 assert(secondop[0] == '<' && secondop[1] == '=');
17115 lhsstrptr = (char *)str;
17116 varstrptr = firstop + 2;
17117 rhsstrptr = secondop + 2;
17118 }
17119 else
17120 {
17121 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17122 lhsstrptr = NULL;
17123 varstrptr = (char *)str;
17124 rhsstrptr = firstop + 2;
17125 }
17126 break;
17127 case '>':
17128 assert(firstop[1] == '=');
17129 assert(secondop == NULL);
17130 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17131 lhsstrptr = firstop + 2;
17132 break;
17133 case '=':
17134 assert(firstop[1] == '=');
17135 assert(secondop == NULL);
17136 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17137 rhsstrptr = firstop + 2;
17138 lhsstrptr = firstop + 2;
17139 break;
17140 case '[':
17141 assert(strncmp(firstop, "[free]", 6) == 0);
17142 assert(secondop == NULL);
17143 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17144 break;
17145 default:
17146 /* it should not be possible that a different character appears in that position */
17147 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17148 return SCIP_READERROR;
17149 }
17150
17151 /* parse left hand side, if necessary */
17152 if( lhsstrptr != NULL )
17153 {
17154 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17155 {
17156 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17157 return SCIP_OKAY;
17158 }
17159
17160 /* in case of an equation, assign the left also to the right hand side */
17161 if( rhsstrptr == lhsstrptr )
17162 rhs = lhs;
17163 }
17164
17165 /* parse right hand side, if different from left hand side */
17166 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17167 {
17168 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17169 {
17170 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17171 return SCIP_OKAY;
17172 }
17173 }
17174
17175 /* initialize buffers for storing the variables and coefficients */
17176 coefssize = 100;
17177 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17178 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17179
17180 assert(varstrptr != NULL);
17181
17182 /* parse linear sum to get variables and coefficients */
17183 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17184
17185 if( *success && requsize > coefssize )
17186 {
17187 /* realloc buffers and try again */
17188 coefssize = requsize;
17189 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17190 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17191
17192 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17193 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17194 }
17195
17196 if( !*success )
17197 {
17198 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17199 }
17200 else
17201 {
17202 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17203 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17204 }
17205
17206 SCIPfreeBufferArray(scip, &coefs);
17207 SCIPfreeBufferArray(scip, &vars);
17208
17209 return SCIP_OKAY;
17210}
17211
17212
17213/** constraint method of constraint handler which returns the variables (if possible) */
17214static
17215SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17216{ /*lint --e{715}*/
17217 SCIP_CONSDATA* consdata;
17218
17219 consdata = SCIPconsGetData(cons);
17220 assert(consdata != NULL);
17221
17222 if( varssize < consdata->nvars )
17223 (*success) = FALSE;
17224 else
17225 {
17226 assert(vars != NULL);
17227
17228 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17229 (*success) = TRUE;
17230 }
17231
17232 return SCIP_OKAY;
17233}
17234
17235/**! [Callback for the number of variables]*/
17236/** constraint method of constraint handler which returns the number of variables (if possible) */
17237static
17238SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17239{ /*lint --e{715}*/
17240 SCIP_CONSDATA* consdata;
17241
17242 consdata = SCIPconsGetData(cons);
17243 assert(consdata != NULL);
17244
17245 (*nvars) = consdata->nvars;
17246 (*success) = TRUE;
17247
17248 return SCIP_OKAY;
17249}
17250/**! [Callback for the number of variables]*/
17251
17252/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17253static
17254SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17255{ /*lint --e{715}*/
17256 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17257
17258 return SCIP_OKAY;
17259}
17260
17261/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17262static
17263SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17264{ /*lint --e{715}*/
17265 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17266
17267 return SCIP_OKAY;
17268}
17269
17270/*
17271 * Callback methods of event handler
17272 */
17273
17274/** execution method of event handler */
17275static
17276SCIP_DECL_EVENTEXEC(eventExecLinear)
17277{ /*lint --e{715}*/
17278 SCIP_CONS* cons;
17279 SCIP_CONSDATA* consdata;
17280 SCIP_VAR* var;
17281 SCIP_EVENTTYPE eventtype;
17282
17283 assert(scip != NULL);
17284 assert(eventhdlr != NULL);
17285 assert(eventdata != NULL);
17286 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17287 assert(event != NULL);
17288
17289 cons = eventdata->cons;
17290 assert(cons != NULL);
17291 consdata = SCIPconsGetData(cons);
17292 assert(consdata != NULL);
17293
17294 /* we can skip events droped for deleted constraints */
17295 if( SCIPconsIsDeleted(cons) )
17296 return SCIP_OKAY;
17297
17298 eventtype = SCIPeventGetType(event);
17299 var = SCIPeventGetVar(event);
17300
17301 if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17302 {
17303 SCIP_Real oldbound;
17304 SCIP_Real newbound;
17305 SCIP_Real val;
17306 int varpos;
17307
17308 varpos = eventdata->varpos;
17309 assert(0 <= varpos && varpos < consdata->nvars);
17310 oldbound = SCIPeventGetOldbound(event);
17311 newbound = SCIPeventGetNewbound(event);
17312 assert(var != NULL);
17313 assert(consdata->vars[varpos] == var);
17314 val = consdata->vals[varpos];
17315
17316 /* we only need to update the activities if the constraint is active,
17317 * otherwise we mark them to be invalid
17318 */
17319 if( SCIPconsIsActive(cons) )
17320 {
17321 /* update the activity values */
17322 if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17323 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17324 else
17325 {
17326 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17327 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17328 }
17329 }
17330 else
17332
17333 consdata->presolved = FALSE;
17334 consdata->rangedrowpropagated = 0;
17335
17336 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17337 if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17338 {
17340
17341 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17342 if( consdata->maxactdeltavar == var )
17343 {
17344 consdata->maxactdelta = SCIP_INVALID;
17345 consdata->maxactdeltavar = NULL;
17346 }
17347
17348 /* check whether bound tightening might now be successful */
17349 if( consdata->boundstightened > 0)
17350 {
17351 switch( eventtype )
17352 {
17354 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17355 consdata->boundstightened = 0;
17356 break;
17358 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17359 consdata->boundstightened = 0;
17360 break;
17361 default:
17362 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17363 return SCIP_INVALIDDATA;
17364 }
17365 }
17366 }
17367 /* update maximal activity delta if a bound was relaxed */
17368 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17369 {
17370 SCIP_Real lb;
17371 SCIP_Real ub;
17372 SCIP_Real domain;
17373 SCIP_Real delta;
17374
17375 assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17376
17377 lb = SCIPvarGetLbLocal(var);
17378 ub = SCIPvarGetUbLocal(var);
17379
17380 domain = ub - lb;
17381 delta = REALABS(val) * domain;
17382
17383 if( delta > consdata->maxactdelta )
17384 {
17385 consdata->maxactdelta = delta;
17386 consdata->maxactdeltavar = var;
17387 }
17388 }
17389 }
17390 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17391 {
17392 /* we want to remove the fixed variable */
17393 consdata->presolved = FALSE;
17394 consdata->removedfixings = FALSE;
17395 consdata->rangedrowpropagated = 0;
17396
17397 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17398 if( consdata->maxactdeltavar == var )
17399 {
17400 consdata->maxactdelta = SCIP_INVALID;
17401 consdata->maxactdeltavar = NULL;
17402 }
17403 }
17404 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17405 {
17406 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17409 consdata->presolved = FALSE;
17410 }
17411 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17412 {
17413 SCIP_Real oldbound;
17414 SCIP_Real newbound;
17415 SCIP_Real val;
17416 int varpos;
17417
17418 varpos = eventdata->varpos;
17419 assert(0 <= varpos && varpos < consdata->nvars);
17420 oldbound = SCIPeventGetOldbound(event);
17421 newbound = SCIPeventGetNewbound(event);
17422 assert(var != NULL);
17423 assert(consdata->vars[varpos] == var);
17424 val = consdata->vals[varpos];
17425
17426 consdata->rangedrowpropagated = 0;
17427
17428 /* update the activity values */
17429 if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17430 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17431 else
17432 {
17433 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17434 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17435 }
17436
17437 /* if the variable is binary but not fixed it had to become binary due to this global change */
17439 {
17441 consdata->indexsorted = FALSE;
17442 else
17443 consdata->coefsorted = FALSE;
17444 }
17445 }
17446 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17447 {
17449
17450 /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17451 consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17452
17453 /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17454 consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17455 }
17456 else
17457 {
17458 assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17459 consdata->varsdeleted = TRUE;
17460 }
17461
17462 return SCIP_OKAY;
17463}
17464
17465
17466/*
17467 * Callback methods of conflict handler
17468 */
17469
17470/** conflict processing method of conflict handler (called when conflict was found) */
17471static
17472SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17473{ /*lint --e{715}*/
17474 SCIP_VAR** vars;
17475 SCIP_Real* vals;
17476 SCIP_Real lhs;
17477 int i;
17478
17479 assert(scip != NULL);
17480 assert(conflicthdlr != NULL);
17481 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17482 assert(bdchginfos != NULL || nbdchginfos == 0);
17483 assert(result != NULL);
17484
17485 /* don't process already resolved conflicts */
17486 if( resolved )
17487 {
17488 *result = SCIP_DIDNOTRUN;
17489 return SCIP_OKAY;
17490 }
17491
17492 *result = SCIP_DIDNOTFIND;
17493
17494 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17495 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17496 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17497 lhs = 1.0;
17498 for( i = 0; i < nbdchginfos; ++i )
17499 {
17500 assert(bdchginfos != NULL);
17501
17502 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17503
17504 /* we can only treat binary variables */
17505 /**@todo extend linear conflict constraints to some non-binary cases */
17506 if( !SCIPvarIsBinary(vars[i]) )
17507 break;
17508
17509 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17510 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17511 vals[i] = 1.0;
17512 else
17513 {
17514 vals[i] = -1.0;
17515 lhs -= 1.0;
17516 }
17517 }
17518
17519 if( i == nbdchginfos )
17520 {
17521 SCIP_CONS* cons;
17522 SCIP_CONS* upgdcons;
17523 char consname[SCIP_MAXSTRLEN];
17524
17525 /* create a constraint out of the conflict set */
17527 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17528 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17529
17530 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17531 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17532 if( upgdcons != NULL )
17533 {
17534 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17535 cons = upgdcons;
17536 }
17537
17538 /* add conflict to SCIP */
17539 SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17540
17541 *result = SCIP_CONSADDED;
17542 }
17543
17544 /* free temporary memory */
17545 SCIPfreeBufferArray(scip, &vals);
17546 SCIPfreeBufferArray(scip, &vars);
17547
17548 return SCIP_OKAY;
17549}
17550
17551
17552/*
17553 * Nonlinear constraint upgrading
17554 */
17555
17556/** tries to upgrade a nonlinear constraint into a linear constraint */
17557static
17558SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17559{
17560 SCIP_CONSDATA* consdata;
17561 SCIP_EXPR* expr;
17562 SCIP_Real lhs;
17563 SCIP_Real rhs;
17564 int i;
17565
17566 assert(nupgdconss != NULL);
17567 assert(upgdconss != NULL);
17568 assert(upgdconsssize > 0);
17569
17570 expr = SCIPgetExprNonlinear(cons);
17571 assert(expr != NULL);
17572
17573 /* not a linear constraint if the expression is not a sum
17574 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17575 */
17576 if( !SCIPisExprSum(scip, expr) )
17577 return SCIP_OKAY;
17578
17579 /* if at least one child is not a variable, then not a linear constraint */
17580 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17581 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17582 return SCIP_OKAY;
17583
17584 /* consider constant part of the sum expression */
17587
17588 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17589 0, NULL, NULL, lhs, rhs,
17593 SCIPconsIsStickingAtNode(cons)) );
17594 assert(upgdconss[0] != NULL);
17595
17596 consdata = SCIPconsGetData(upgdconss[0]);
17597
17598 /* add linear terms */
17600 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17601 {
17603 }
17604
17605 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17606 consdata->checkabsolute = TRUE;
17607
17608 *nupgdconss = 1;
17609
17610 SCIPdebugMsg(scip, "created linear constraint:\n");
17611 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17612
17613 return SCIP_OKAY;
17614} /*lint !e715*/
17615
17616/*
17617 * constraint specific interface methods
17618 */
17619
17620/** creates the handler for linear constraints and includes it in SCIP */
17622 SCIP* scip /**< SCIP data structure */
17623 )
17624{
17625 SCIP_CONSHDLRDATA* conshdlrdata;
17626 SCIP_CONSHDLR* conshdlr;
17627 SCIP_EVENTHDLR* eventhdlr;
17628 SCIP_CONFLICTHDLR* conflicthdlr;
17629
17630 assert(scip != NULL);
17631
17632 /* create event handler for bound change events */
17634 eventExecLinear, NULL) );
17635
17636 /* create conflict handler for linear constraints */
17638 conflictExecLinear, NULL) );
17639
17640 /* create constraint handler data */
17641 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17642
17643 /* include constraint handler */
17646 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17647 conshdlrdata) );
17648
17649 assert(conshdlr != NULL);
17650
17651 /* set non-fundamental callbacks via specific setter functions */
17652 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17653 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17654 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17655 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17656 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17657 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17658 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17659 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17660 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17661 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17662 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17663 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17664 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17665 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17666 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17668 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17671 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17672 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17674 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17675 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17676 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17677 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17678
17679 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17680 {
17681 /* include the linear constraint upgrade in the nonlinear constraint handler */
17683 }
17684
17685 /* add linear constraint handler parameters */
17687 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17688 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17689 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17691 "constraints/" CONSHDLR_NAME "/maxrounds",
17692 "maximal number of separation rounds per node (-1: unlimited)",
17693 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17695 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17696 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17697 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17699 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17700 "maximal number of cuts separated per separation round",
17701 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17703 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17704 "maximal number of cuts separated per separation round in the root node",
17705 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17707 "constraints/" CONSHDLR_NAME "/presolpairwise",
17708 "should pairwise constraint comparison be performed in presolving?",
17709 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17711 "constraints/" CONSHDLR_NAME "/presolusehashing",
17712 "should hash table be used for detecting redundant constraints in advance",
17713 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17715 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17716 "number for minimal pairwise presolve comparisons",
17717 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17719 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17720 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17721 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17723 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17724 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17725 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17727 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17728 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17729 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17731 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17732 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17733 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17735 "constraints/" CONSHDLR_NAME "/separateall",
17736 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17737 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17739 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17740 "should presolving search for aggregations in equations",
17741 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17743 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17744 "should presolving try to simplify inequalities",
17745 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17747 "constraints/" CONSHDLR_NAME "/dualpresolving",
17748 "should dual presolving steps be performed?",
17749 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17751 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17752 "should stuffing of singleton continuous variables be performed?",
17753 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17755 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17756 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17757 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17759 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17760 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17762 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17763 "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)?",
17764 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17766 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17767 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17768 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17770 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17771 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17772 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17774 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17775 "should presolving try to detect subsets of constraints parallel to the objective function?",
17776 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17778 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17779 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17780 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17782 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17783 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17784 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17786 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17787 "maximum depth to apply ranged row propagation",
17788 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17790 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17791 "frequency for applying ranged row propagation",
17792 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17794 "constraints/" CONSHDLR_NAME "/multaggrremove",
17795 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17796 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17798 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17799 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17800 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17802 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17803 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17804 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17806 "constraints/" CONSHDLR_NAME "/extractcliques",
17807 "should Cliques be extracted?",
17808 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17809
17810 return SCIP_OKAY;
17811}
17812
17813/** includes a linear constraint update method into the linear constraint handler */
17815 SCIP* scip, /**< SCIP data structure */
17816 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17817 int priority, /**< priority of upgrading method */
17818 const char* conshdlrname /**< name of the constraint handler */
17819 )
17820{
17821 SCIP_CONSHDLR* conshdlr;
17822 SCIP_CONSHDLRDATA* conshdlrdata;
17823 SCIP_LINCONSUPGRADE* linconsupgrade;
17825 char paramdesc[SCIP_MAXSTRLEN];
17826
17827 assert(scip != NULL);
17828 assert(linconsupgd != NULL);
17829 assert(conshdlrname != NULL );
17830
17831 /* find the linear constraint handler */
17832 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17833 if( conshdlr == NULL )
17834 {
17835 SCIPerrorMessage("linear constraint handler not found\n");
17836 return SCIP_PLUGINNOTFOUND;
17837 }
17838
17839 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17840 assert(conshdlrdata != NULL);
17841
17842 /* check if linear constraint update method already exists in constraint handler data */
17843 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17844 {
17845 /* create a linear constraint upgrade data object */
17846 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17847
17848 /* insert linear constraint update method into constraint handler data */
17849 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17850
17851 /* adds parameter to turn on and off the upgrading step */
17852 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17853 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17855 paramname, paramdesc,
17856 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17857 }
17858
17859 return SCIP_OKAY;
17860}
17861
17862/** creates and captures a linear constraint
17863 *
17864 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17865 */
17867 SCIP* scip, /**< SCIP data structure */
17868 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17869 const char* name, /**< name of constraint */
17870 int nvars, /**< number of nonzeros in the constraint */
17871 SCIP_VAR** vars, /**< array with variables of constraint entries */
17872 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17873 SCIP_Real lhs, /**< left hand side of constraint */
17874 SCIP_Real rhs, /**< right hand side of constraint */
17875 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17876 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17877 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17878 * Usually set to TRUE. */
17879 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17880 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17881 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17882 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17883 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17884 * Usually set to TRUE. */
17885 SCIP_Bool local, /**< is constraint only valid locally?
17886 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17887 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17888 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17889 * adds coefficients to this constraint. */
17890 SCIP_Bool dynamic, /**< is constraint subject to aging?
17891 * Usually set to FALSE. Set to TRUE for own cuts which
17892 * are separated as constraints. */
17893 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17894 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17895 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17896 * if it may be moved to a more global node?
17897 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17898 )
17899{
17900 SCIP_CONSHDLR* conshdlr;
17901 SCIP_CONSDATA* consdata;
17902 int j;
17903
17904 assert(scip != NULL);
17905 assert(cons != NULL);
17906
17907 /* find the linear constraint handler */
17908 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17909 if( conshdlr == NULL )
17910 {
17911 SCIPerrorMessage("linear constraint handler not found\n");
17912 return SCIP_PLUGINNOTFOUND;
17913 }
17914
17915 for( j = 0; j < nvars; ++j )
17916 {
17917 if( SCIPisInfinity(scip, REALABS(vals[j])) )
17918 {
17919 SCIPerrorMessage("coefficient of variable <%s> is infinite.\n", SCIPvarGetName(vars[j]));
17920 SCIPABORT();
17921 return SCIP_INVALIDDATA;
17922 }
17923 }
17924
17925 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17926 * constraint after presolving we have to ensure that it holds active variables
17927 */
17928 if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17929 {
17930 SCIP_VAR** consvars;
17931 SCIP_Real* consvals;
17932 SCIP_Real constant = 0.0;
17933 int nconsvars;
17934 int requiredsize;
17935
17936 nconsvars = nvars;
17937 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17938 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17939
17940 /* get active variables for new constraint */
17941 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17942
17943 /* if space was not enough we need to resize the buffers */
17944 if( requiredsize > nconsvars )
17945 {
17946 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17947 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17948
17949 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17950 assert(requiredsize <= nconsvars);
17951 }
17952
17953 /* adjust sides and check that we do not subtract infinity values */
17954 if( SCIPisInfinity(scip, REALABS(constant)) )
17955 {
17956 if( constant < 0.0 )
17957 {
17958 if( SCIPisInfinity(scip, lhs) )
17959 {
17960 SCIPfreeBufferArray(scip, &consvals);
17961 SCIPfreeBufferArray(scip, &consvars);
17962
17963 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);
17964
17965 SCIPABORT();
17966 return SCIP_INVALIDDATA; /*lint !e527*/
17967 }
17968 if( SCIPisInfinity(scip, rhs) )
17969 {
17970 SCIPfreeBufferArray(scip, &consvals);
17971 SCIPfreeBufferArray(scip, &consvars);
17972
17973 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);
17974
17975 SCIPABORT();
17976 return SCIP_INVALIDDATA; /*lint !e527*/
17977 }
17978
17979 lhs = -SCIPinfinity(scip);
17980 rhs = -SCIPinfinity(scip);
17981 }
17982 else
17983 {
17984 if( SCIPisInfinity(scip, -lhs) )
17985 {
17986 SCIPfreeBufferArray(scip, &consvals);
17987 SCIPfreeBufferArray(scip, &consvars);
17988
17989 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);
17990
17991 SCIPABORT();
17992 return SCIP_INVALIDDATA; /*lint !e527*/
17993 }
17994 if( SCIPisInfinity(scip, -rhs) )
17995 {
17996 SCIPfreeBufferArray(scip, &consvals);
17997 SCIPfreeBufferArray(scip, &consvars);
17998
17999 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);
18000
18001 SCIPABORT();
18002 return SCIP_INVALIDDATA; /*lint !e527*/
18003 }
18004
18005 lhs = SCIPinfinity(scip);
18006 rhs = SCIPinfinity(scip);
18007 }
18008 }
18009 else
18010 {
18011 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18012 lhs -= constant;
18013 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18014 rhs -= constant;
18015
18016 if( SCIPisInfinity(scip, -lhs) )
18017 lhs = -SCIPinfinity(scip);
18018 else if( SCIPisInfinity(scip, lhs) )
18019 lhs = SCIPinfinity(scip);
18020
18021 if( SCIPisInfinity(scip, rhs) )
18022 rhs = SCIPinfinity(scip);
18023 else if( SCIPisInfinity(scip, -rhs) )
18024 rhs = -SCIPinfinity(scip);
18025 }
18026
18027 /* create constraint data */
18028 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
18029 assert(consdata != NULL);
18030
18031 SCIPfreeBufferArray(scip, &consvals);
18032 SCIPfreeBufferArray(scip, &consvars);
18033 }
18034 else
18035 {
18036 /* create constraint data */
18037 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18038 assert(consdata != NULL);
18039 }
18040
18041#ifndef NDEBUG
18042 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18043 if( check || enforce )
18044 {
18045 int n;
18046 for(n = consdata->nvars - 1; n >= 0; --n )
18047 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18048 }
18049#endif
18050
18051 /* create constraint */
18052 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18053 local, modifiable, dynamic, removable, stickingatnode) );
18054
18055 return SCIP_OKAY;
18056}
18057
18058/** creates and captures a linear constraint
18059 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18060 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18061 *
18062 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18063 *
18064 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18065 */
18067 SCIP* scip, /**< SCIP data structure */
18068 SCIP_CONS** cons, /**< pointer to hold the created constraint */
18069 const char* name, /**< name of constraint */
18070 int nvars, /**< number of nonzeros in the constraint */
18071 SCIP_VAR** vars, /**< array with variables of constraint entries */
18072 SCIP_Real* vals, /**< array with coefficients of constraint entries */
18073 SCIP_Real lhs, /**< left hand side of constraint */
18074 SCIP_Real rhs /**< right hand side of constraint */
18075 )
18076{
18077 assert(scip != NULL);
18078
18079 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18081
18082 return SCIP_OKAY;
18083}
18084
18085/** creates by copying and captures a linear constraint */
18087 SCIP* scip, /**< target SCIP data structure */
18088 SCIP_CONS** cons, /**< pointer to store the created target constraint */
18089 SCIP* sourcescip, /**< source SCIP data structure */
18090 const char* name, /**< name of constraint */
18091 int nvars, /**< number of variables in source variable array */
18092 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18093 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18094 SCIP_Real lhs, /**< left hand side of the linear constraint */
18095 SCIP_Real rhs, /**< right hand side of the linear constraint */
18096 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18097 * variables of the target SCIP */
18098 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18099 * target constraints */
18100 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18101 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18102 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18103 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18104 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18105 SCIP_Bool local, /**< is constraint only valid locally? */
18106 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18107 SCIP_Bool dynamic, /**< is constraint subject to aging? */
18108 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18109 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18110 * if it may be moved to a more global node? */
18111 SCIP_Bool global, /**< create a global or a local copy? */
18112 SCIP_Bool* valid /**< pointer to store if the copying was valid */
18113 )
18114{
18115 SCIP_VAR** vars;
18116 SCIP_Real* coefs;
18117
18118 SCIP_Real constant;
18119 int requiredsize;
18120 int v;
18121 SCIP_Bool success;
18122
18123 if( SCIPisGT(scip, lhs, rhs) )
18124 {
18125 *valid = FALSE;
18126 return SCIP_OKAY;
18127 }
18128
18129 (*valid) = TRUE;
18130
18131 if( nvars == 0 )
18132 {
18133 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18134 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18135 return SCIP_OKAY;
18136 }
18137
18138 /* duplicate variable array */
18139 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
18140
18141 /* duplicate coefficient array */
18142 if( sourcecoefs != NULL )
18143 {
18144 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18145 }
18146 else
18147 {
18148 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18149 for( v = 0; v < nvars; ++v )
18150 coefs[v] = 1.0;
18151 }
18152
18153 constant = 0.0;
18154
18155 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18156 * the target SCIP
18157 */
18158 if( !SCIPvarIsOriginal(vars[0]) )
18159 {
18160 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18161
18162 if( requiredsize > nvars )
18163 {
18164 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18165 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18166
18167 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18168 assert(requiredsize <= nvars);
18169 }
18170 }
18171 else
18172 {
18173 for( v = 0; v < nvars; ++v )
18174 {
18175 assert(SCIPvarIsOriginal(vars[v]));
18176 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18177 assert(vars[v] != NULL);
18178 }
18179 }
18180
18181 success = TRUE;
18182 /* map variables of the source constraint to variables of the target SCIP */
18183 for( v = 0; v < nvars && success; ++v )
18184 {
18185 SCIP_VAR* var;
18186 var = vars[v];
18187
18188 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18189 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18190
18191 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18192 assert(!(success) || vars[v] != NULL);
18193 }
18194
18195 /* only create the target constraint, if all variables could be copied */
18196 if( success )
18197 {
18198 if( !SCIPisInfinity(scip, -lhs) )
18199 lhs -= constant;
18200
18201 if( !SCIPisInfinity(scip, rhs) )
18202 rhs -= constant;
18203
18204 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18205 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18206 }
18207 else
18208 *valid = FALSE;
18209
18210 /* free buffer array */
18211 SCIPfreeBufferArray(scip, &coefs);
18212 SCIPfreeBufferArray(scip, &vars);
18213
18214 return SCIP_OKAY;
18215}
18216
18217/** adds coefficient to linear constraint (if it is not zero) */
18219 SCIP* scip, /**< SCIP data structure */
18220 SCIP_CONS* cons, /**< constraint data */
18221 SCIP_VAR* var, /**< variable of constraint entry */
18222 SCIP_Real val /**< coefficient of constraint entry */
18223 )
18224{
18225 assert(scip != NULL);
18226 assert(cons != NULL);
18227 assert(var != NULL);
18228
18229 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18230 {
18231 SCIPerrorMessage("constraint is not linear\n");
18232 return SCIP_INVALIDDATA;
18233 }
18234
18235 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18236 * constraint after presolving we have to ensure that it holds active variables
18237 */
18239 {
18240 SCIP_CONSDATA* consdata;
18241 SCIP_VAR** consvars;
18242 SCIP_Real* consvals;
18243 SCIP_Real constant = 0.0;
18244 SCIP_Real rhs;
18245 SCIP_Real lhs;
18246 int nconsvars;
18247 int requiredsize;
18248 int v;
18249
18250 nconsvars = 1;
18251 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18252 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18253 consvars[0] = var;
18254 consvals[0] = val;
18255
18256 /* get active variables for new constraint */
18257 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18258
18259 /* if space was not enough we need to resize the buffers */
18260 if( requiredsize > nconsvars )
18261 {
18262 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18263 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18264
18265 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18266 assert(requiredsize <= nconsvars);
18267 }
18268
18269 consdata = SCIPconsGetData(cons);
18270 assert(consdata != NULL);
18271
18272 lhs = consdata->lhs;
18273 rhs = consdata->rhs;
18274
18275 /* adjust sides and check that we do not subtract infinity values */
18276 /* constant is infinite */
18277 if( SCIPisInfinity(scip, REALABS(constant)) )
18278 {
18279 if( constant < 0.0 )
18280 {
18281 if( SCIPisInfinity(scip, lhs) )
18282 {
18283 SCIPfreeBufferArray(scip, &consvals);
18284 SCIPfreeBufferArray(scip, &consvars);
18285
18286 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));
18287
18288 SCIPABORT();
18289 return SCIP_INVALIDDATA; /*lint !e527*/
18290 }
18291 if( SCIPisInfinity(scip, rhs) )
18292 {
18293 SCIPfreeBufferArray(scip, &consvals);
18294 SCIPfreeBufferArray(scip, &consvars);
18295
18296 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));
18297
18298 SCIPABORT();
18299 return SCIP_INVALIDDATA; /*lint !e527*/
18300 }
18301
18302 lhs = -SCIPinfinity(scip);
18303 rhs = -SCIPinfinity(scip);
18304 }
18305 else
18306 {
18307 if( SCIPisInfinity(scip, -lhs) )
18308 {
18309 SCIPfreeBufferArray(scip, &consvals);
18310 SCIPfreeBufferArray(scip, &consvars);
18311
18312 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));
18313
18314 SCIPABORT();
18315 return SCIP_INVALIDDATA; /*lint !e527*/
18316 }
18317 if( SCIPisInfinity(scip, -rhs) )
18318 {
18319 SCIPfreeBufferArray(scip, &consvals);
18320 SCIPfreeBufferArray(scip, &consvars);
18321
18322 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));
18323
18324 SCIPABORT();
18325 return SCIP_INVALIDDATA; /*lint !e527*/
18326 }
18327
18328 lhs = SCIPinfinity(scip);
18329 rhs = SCIPinfinity(scip);
18330 }
18331 }
18332 /* constant is not infinite */
18333 else
18334 {
18335 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18336 lhs -= constant;
18337 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18338 rhs -= constant;
18339
18340 if( SCIPisInfinity(scip, -lhs) )
18341 lhs = -SCIPinfinity(scip);
18342 else if( SCIPisInfinity(scip, lhs) )
18343 lhs = SCIPinfinity(scip);
18344
18345 if( SCIPisInfinity(scip, rhs) )
18346 rhs = SCIPinfinity(scip);
18347 else if( SCIPisInfinity(scip, -rhs) )
18348 rhs = -SCIPinfinity(scip);
18349 }
18350
18351 /* add all active variables to constraint */
18352 for( v = nconsvars - 1; v >= 0; --v )
18353 {
18354 if( !SCIPisZero(scip, consvals[v]) )
18355 {
18356 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18357 }
18358 }
18359
18360 /* update left and right hand sides */
18361 SCIP_CALL( chgLhs(scip, cons, lhs));
18362 SCIP_CALL( chgRhs(scip, cons, rhs));
18363
18364 SCIPfreeBufferArray(scip, &consvals);
18365 SCIPfreeBufferArray(scip, &consvars);
18366 }
18367 else if( !SCIPisZero(scip, val) )
18368 {
18369 SCIP_CALL( addCoef(scip, cons, var, val) );
18370 }
18371
18372 return SCIP_OKAY;
18373}
18374
18375/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18376 * not yet contained in the constraint
18377 *
18378 * @note This method may only be called during problem creation stage for an original constraint and variable.
18379 *
18380 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18381 */
18383 SCIP* scip, /**< SCIP data structure */
18384 SCIP_CONS* cons, /**< constraint data */
18385 SCIP_VAR* var, /**< variable of constraint entry */
18386 SCIP_Real val /**< new coefficient of constraint entry */
18387 )
18388{
18389 SCIP_CONSDATA* consdata;
18390 SCIP_VAR** vars;
18391 SCIP_Bool found;
18392 int i;
18393
18394 assert(scip != NULL);
18395 assert(cons != NULL);
18396 assert(var != NULL);
18397
18398 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18399 {
18400 SCIPerrorMessage("constraint is not linear\n");
18401 return SCIP_INVALIDDATA;
18402 }
18403
18405 {
18406 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18407 return SCIP_INVALIDDATA;
18408 }
18409
18410 consdata = SCIPconsGetData(cons);
18411 assert(consdata != NULL);
18412
18413 vars = consdata->vars;
18414 found = FALSE;
18415 i = 0;
18416 while( i < consdata->nvars )
18417 {
18418 if( vars[i] == var )
18419 {
18420 if( found || SCIPisZero(scip, val) )
18421 {
18422 SCIP_CALL( delCoefPos(scip, cons, i) );
18423
18424 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18425 i--;
18426 }
18427 else
18428 {
18429 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18430 }
18431 found = TRUE;
18432 }
18433 i++;
18434 }
18435
18436 if( !found )
18437 {
18438 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18439 }
18440
18441 return SCIP_OKAY;
18442}
18443
18444/** deletes variable from linear constraint
18445 *
18446 * @note This method may only be called during problem creation stage for an original constraint and variable.
18447 *
18448 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18449 */
18451 SCIP* scip, /**< SCIP data structure */
18452 SCIP_CONS* cons, /**< constraint data */
18453 SCIP_VAR* var /**< variable of constraint entry */
18454 )
18455{
18456 assert(scip != NULL);
18457 assert(cons != NULL);
18458 assert(var != NULL);
18459
18460 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18461
18462 return SCIP_OKAY;
18463}
18464
18465/** gets left hand side of linear constraint */
18467 SCIP* scip, /**< SCIP data structure */
18468 SCIP_CONS* cons /**< constraint data */
18469 )
18470{
18471 SCIP_CONSDATA* consdata;
18472
18473 assert(scip != NULL);
18474 assert(cons != NULL);
18475
18476 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18477 {
18478 SCIPerrorMessage("constraint is not linear\n");
18479 SCIPABORT();
18480 return SCIP_INVALID; /*lint !e527*/
18481 }
18482
18483 consdata = SCIPconsGetData(cons);
18484 assert(consdata != NULL);
18485
18486 return consdata->lhs;
18487}
18488
18489/** gets right hand side of linear constraint */
18491 SCIP* scip, /**< SCIP data structure */
18492 SCIP_CONS* cons /**< constraint data */
18493 )
18494{
18495 SCIP_CONSDATA* consdata;
18496
18497 assert(scip != NULL);
18498 assert(cons != NULL);
18499
18500 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18501 {
18502 SCIPerrorMessage("constraint is not linear\n");
18503 SCIPABORT();
18504 return SCIP_INVALID; /*lint !e527*/
18505 }
18506
18507 consdata = SCIPconsGetData(cons);
18508 assert(consdata != NULL);
18509
18510 return consdata->rhs;
18511}
18512
18513/** changes left hand side of linear constraint */
18515 SCIP* scip, /**< SCIP data structure */
18516 SCIP_CONS* cons, /**< constraint data */
18517 SCIP_Real lhs /**< new left hand side */
18518 )
18519{
18520 assert(scip != NULL);
18521 assert(cons != NULL);
18522
18523 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18524 {
18525 SCIPerrorMessage("constraint is not linear\n");
18526 return SCIP_INVALIDDATA;
18527 }
18528
18529 SCIP_CALL( chgLhs(scip, cons, lhs) );
18530
18531 return SCIP_OKAY;
18532}
18533
18534/** changes right hand side of linear constraint */
18536 SCIP* scip, /**< SCIP data structure */
18537 SCIP_CONS* cons, /**< constraint data */
18538 SCIP_Real rhs /**< new right hand side */
18539 )
18540{
18541 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18542 {
18543 SCIPerrorMessage("constraint is not linear\n");
18544 return SCIP_INVALIDDATA;
18545 }
18546
18547 SCIP_CALL( chgRhs(scip, cons, rhs) );
18548
18549 return SCIP_OKAY;
18550}
18551
18552/** gets the number of variables in the linear constraint */
18554 SCIP* scip, /**< SCIP data structure */
18555 SCIP_CONS* cons /**< constraint data */
18556 )
18557{
18558 SCIP_CONSDATA* consdata;
18559
18560 assert(scip != NULL);
18561 assert(cons != NULL);
18562
18563 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18564 {
18565 SCIPerrorMessage("constraint is not linear\n");
18566 SCIPABORT();
18567 return -1; /*lint !e527*/
18568 }
18569
18570 consdata = SCIPconsGetData(cons);
18571 assert(consdata != NULL);
18572
18573 return consdata->nvars;
18574}
18575
18576/** gets the array of variables in the linear constraint; the user must not modify this array! */
18578 SCIP* scip, /**< SCIP data structure */
18579 SCIP_CONS* cons /**< constraint data */
18580 )
18581{
18582 SCIP_CONSDATA* consdata;
18583
18584 assert(scip != NULL);
18585 assert(cons != NULL);
18586
18587 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18588 {
18589 SCIPerrorMessage("constraint is not linear\n");
18590 SCIPABORT();
18591 return NULL; /*lint !e527*/
18592 }
18593
18594 consdata = SCIPconsGetData(cons);
18595 assert(consdata != NULL);
18596
18597 return consdata->vars;
18598}
18599
18600/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18602 SCIP* scip, /**< SCIP data structure */
18603 SCIP_CONS* cons /**< constraint data */
18604 )
18605{
18606 SCIP_CONSDATA* consdata;
18607
18608 assert(scip != NULL);
18609 assert(cons != NULL);
18610
18611 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18612 {
18613 SCIPerrorMessage("constraint is not linear\n");
18614 SCIPABORT();
18615 return NULL; /*lint !e527*/
18616 }
18617
18618 consdata = SCIPconsGetData(cons);
18619 assert(consdata != NULL);
18620
18621 return consdata->vals;
18622}
18623
18624/** gets the activity of the linear constraint in the given solution
18625 *
18626 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18627 * comprises positive and negative infinity contributions
18628 */
18630 SCIP* scip, /**< SCIP data structure */
18631 SCIP_CONS* cons, /**< constraint data */
18632 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18633 )
18634{
18635 SCIP_CONSDATA* consdata;
18636
18637 assert(scip != NULL);
18638 assert(cons != NULL);
18639
18640 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18641 {
18642 SCIPerrorMessage("constraint is not linear\n");
18643 SCIPABORT();
18644 return SCIP_INVALID; /*lint !e527*/
18645 }
18646
18647 consdata = SCIPconsGetData(cons);
18648 assert(consdata != NULL);
18649
18650 if( consdata->row != NULL )
18651 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18652 else
18653 return consdataGetActivity(scip, consdata, sol);
18654}
18655
18656/** gets the feasibility of the linear constraint in the given solution */
18658 SCIP* scip, /**< SCIP data structure */
18659 SCIP_CONS* cons, /**< constraint data */
18660 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18661 )
18662{
18663 SCIP_CONSDATA* consdata;
18664
18665 assert(scip != NULL);
18666 assert(cons != NULL);
18667
18668 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18669 {
18670 SCIPerrorMessage("constraint is not linear\n");
18671 SCIPABORT();
18672 return SCIP_INVALID; /*lint !e527*/
18673 }
18674
18675 consdata = SCIPconsGetData(cons);
18676 assert(consdata != NULL);
18677
18678 if( consdata->row != NULL )
18679 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18680 else
18681 return consdataGetFeasibility(scip, consdata, sol);
18682}
18683
18684/** gets the dual solution of the linear constraint in the current LP */
18686 SCIP* scip, /**< SCIP data structure */
18687 SCIP_CONS* cons /**< constraint data */
18688 )
18689{
18690 SCIP_CONSDATA* consdata;
18691
18692 assert(scip != NULL);
18693 assert(cons != NULL);
18694 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18695
18696 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18697 {
18698 SCIPerrorMessage("constraint is not linear\n");
18699 SCIPABORT();
18700 return SCIP_INVALID; /*lint !e527*/
18701 }
18702
18703 consdata = SCIPconsGetData(cons);
18704 assert(consdata != NULL);
18705
18706 if( consdata->row != NULL )
18707 return SCIProwGetDualsol(consdata->row);
18708 else
18709 return 0.0;
18710}
18711
18712/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18714 SCIP* scip, /**< SCIP data structure */
18715 SCIP_CONS* cons /**< constraint data */
18716 )
18717{
18718 SCIP_CONSDATA* consdata;
18719
18720 assert(scip != NULL);
18721 assert(cons != NULL);
18722 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18723
18724 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18725 {
18726 SCIPerrorMessage("constraint is not linear\n");
18727 SCIPABORT();
18728 return SCIP_INVALID; /*lint !e527*/
18729 }
18730
18731 consdata = SCIPconsGetData(cons);
18732 assert(consdata != NULL);
18733
18734 if( consdata->row != NULL )
18735 return SCIProwGetDualfarkas(consdata->row);
18736 else
18737 return 0.0;
18738}
18739
18740/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18741 * the user must not modify the row!
18742 */
18744 SCIP* scip, /**< SCIP data structure */
18745 SCIP_CONS* cons /**< constraint data */
18746 )
18747{
18748 SCIP_CONSDATA* consdata;
18749
18750 assert(scip != NULL);
18751 assert(cons != NULL);
18752
18753 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18754 {
18755 SCIPerrorMessage("constraint is not linear\n");
18756 SCIPABORT();
18757 return NULL; /*lint !e527*/
18758 }
18759
18760 consdata = SCIPconsGetData(cons);
18761 assert(consdata != NULL);
18762
18763 return consdata->row;
18764}
18765
18766/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18768 SCIP* scip, /**< SCIP data structure */
18769 SCIP_CONS* cons, /**< source constraint to try to convert */
18770 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18771 )
18772{
18773 SCIP_CONSHDLR* conshdlr;
18774 SCIP_CONSHDLRDATA* conshdlrdata;
18775 SCIP_CONSDATA* consdata;
18776 SCIP_VAR* var;
18777 SCIP_Real val;
18778 SCIP_Real lb;
18779 SCIP_Real ub;
18780 SCIP_Real poscoeffsum;
18781 SCIP_Real negcoeffsum;
18782 SCIP_Bool infeasible;
18783 SCIP_Bool integral;
18784 int nchgsides = 0;
18785 int nposbin;
18786 int nnegbin;
18787 int nposint;
18788 int nnegint;
18789 int nposimpl;
18790 int nnegimpl;
18791 int nposimplbin;
18792 int nnegimplbin;
18793 int nposcont;
18794 int nnegcont;
18795 int ncoeffspone;
18796 int ncoeffsnone;
18797 int ncoeffspint;
18798 int ncoeffsnint;
18799 int ncoeffspfrac;
18800 int ncoeffsnfrac;
18801 int i;
18802
18803 assert(scip != NULL);
18804 assert(cons != NULL);
18805 assert(upgdcons != NULL);
18806
18807 *upgdcons = NULL;
18808
18809 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18810 if( SCIPconsIsModifiable(cons) )
18811 return SCIP_OKAY;
18812
18813 /* check for upgradability */
18814 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18815 return SCIP_OKAY;
18816
18817 /* get the constraint handler and check, if it's really a linear constraint */
18818 conshdlr = SCIPconsGetHdlr(cons);
18819 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18820 {
18821 SCIPerrorMessage("constraint is not linear\n");
18822 return SCIP_INVALIDDATA;
18823 }
18824
18825 /* get constraint handler data and constraint data */
18826 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18827 assert(conshdlrdata != NULL);
18828 consdata = SCIPconsGetData(cons);
18829 assert(consdata != NULL);
18830
18831 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18832 if( consdata->upgraded )
18833 return SCIP_OKAY;
18834
18835 /* check, if the constraint is already stored as LP row */
18836 if( consdata->row != NULL )
18837 {
18838 if( SCIProwIsInLP(consdata->row) )
18839 {
18840 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18841 return SCIP_INVALIDDATA;
18842 }
18843 else
18844 {
18845 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18846 }
18847 }
18848
18849 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18850
18851 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18852 * skipped and we hope that the infeasibility gets detected later again.
18853 *
18854 * TODO: do we want to try to upgrade the constraint anyway?
18855 *
18856 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18857 * proven to be infeasible.
18858 */
18859 if( infeasible ) /*lint !e774*/
18860 return SCIP_OKAY;
18861
18862 /* tighten sides */
18863 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18864
18865 if( infeasible ) /*lint !e774*/
18866 return SCIP_OKAY;
18867
18868 /*
18869 * calculate some statistics on linear constraint
18870 */
18871
18872 nposbin = 0;
18873 nnegbin = 0;
18874 nposint = 0;
18875 nnegint = 0;
18876 nposimpl = 0;
18877 nnegimpl = 0;
18878 nposimplbin = 0;
18879 nnegimplbin = 0;
18880 nposcont = 0;
18881 nnegcont = 0;
18882 ncoeffspone = 0;
18883 ncoeffsnone = 0;
18884 ncoeffspint = 0;
18885 ncoeffsnint = 0;
18886 ncoeffspfrac = 0;
18887 ncoeffsnfrac = 0;
18888 integral = TRUE;
18889 poscoeffsum = 0.0;
18890 negcoeffsum = 0.0;
18891
18892 for( i = 0; i < consdata->nvars; ++i )
18893 {
18894 var = consdata->vars[i];
18895 val = consdata->vals[i];
18896 lb = SCIPvarGetLbLocal(var);
18897 ub = SCIPvarGetUbLocal(var);
18898 assert(!SCIPisZero(scip, val));
18899
18900 switch( SCIPvarGetType(var) )
18901 {
18903 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18904 integral = integral && SCIPisIntegral(scip, val);
18905 if( val >= 0.0 )
18906 nposbin++;
18907 else
18908 nnegbin++;
18909 break;
18911 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18912 integral = integral && SCIPisIntegral(scip, val);
18913 if( val >= 0.0 )
18914 nposint++;
18915 else
18916 nnegint++;
18917 break;
18919 if( SCIPvarIsBinary(var) )
18920 {
18921 if( val >= 0.0 )
18922 nposimplbin++;
18923 else
18924 nnegimplbin++;
18925 }
18926 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18927 integral = integral && SCIPisIntegral(scip, val);
18928 if( val >= 0.0 )
18929 nposimpl++;
18930 else
18931 nnegimpl++;
18932 break;
18934 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18935 if( val >= 0.0 )
18936 nposcont++;
18937 else
18938 nnegcont++;
18939 break;
18940 default:
18941 SCIPerrorMessage("unknown variable type\n");
18942 return SCIP_INVALIDDATA;
18943 }
18944 if( SCIPisEQ(scip, val, 1.0) )
18945 ncoeffspone++;
18946 else if( SCIPisEQ(scip, val, -1.0) )
18947 ncoeffsnone++;
18948 else if( SCIPisIntegral(scip, val) )
18949 {
18950 if( SCIPisPositive(scip, val) )
18951 ncoeffspint++;
18952 else
18953 ncoeffsnint++;
18954 }
18955 else
18956 {
18957 if( SCIPisPositive(scip, val) )
18958 ncoeffspfrac++;
18959 else
18960 ncoeffsnfrac++;
18961 }
18962 if( SCIPisPositive(scip, val) )
18963 poscoeffsum += val;
18964 else
18965 negcoeffsum += val;
18966 }
18967
18968 /*
18969 * call the upgrading methods
18970 */
18971
18972 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18973 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18974 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",
18975 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18976 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18977 poscoeffsum, negcoeffsum, integral);
18978
18979 /* try all upgrading methods in priority order in case the upgrading step is enable */
18980 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18981 {
18982 if( conshdlrdata->linconsupgrades[i]->active )
18983 {
18984 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18985 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18986 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18987 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18988 poscoeffsum, negcoeffsum, integral,
18989 upgdcons) );
18990 }
18991 }
18992
18993#ifdef SCIP_DEBUG
18994 if( *upgdcons != NULL )
18995 {
18997 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18998 SCIPdebugPrintCons(scip, *upgdcons, NULL);
18999 }
19000#endif
19001
19002 return SCIP_OKAY; /*lint !e438*/
19003}
19004
19005/** cleans up (multi-)aggregations and fixings from linear constraints */
19007 SCIP* scip, /**< SCIP data structure */
19008 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
19009 SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
19010 )
19011{
19012 SCIP_CONSHDLR* conshdlr;
19013 SCIP_CONS** conss;
19014 int nconss;
19015 int i;
19016
19017 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
19018 if( conshdlr == NULL )
19019 return SCIP_OKAY;
19020
19021 assert(infeasible != NULL);
19022 *infeasible = FALSE;
19023
19024 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
19025 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
19026
19027 for( i = 0; i < nconss; ++i )
19028 {
19029 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
19030
19031 if( *infeasible )
19032 break;
19033 }
19034
19035 return SCIP_OKAY;
19036}
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:7881
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:7192
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7476
#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:7948
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:7452
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:9519
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:5013
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:5344
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:9631
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:8921
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:5222
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
Definition: cons_linear.c:5749
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:7575
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:4831
#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:7014
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:9043
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:5078
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:7665
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:5414
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:7813
#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:7539
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:9577
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9463
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:5274
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:5691
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:6734
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:5129
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:5246
#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:7010
Constraint handler for linear constraints in their most general form, .
constraint handler for nonlinear constraints specified by algebraic expressions
defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
#define QUAD_MEMBER(x)
Definition: dbldblarith.h:48
#define SCIPquadprecSumQD(r, a, b)
Definition: dbldblarith.h:62
#define QUAD_ASSIGN(a, constant)
Definition: dbldblarith.h:51
#define QUAD(x)
Definition: dbldblarith.h:47
#define QUAD_ASSIGN_Q(a, b)
Definition: dbldblarith.h:52
#define QUAD_TO_DBL(x)
Definition: dbldblarith.h:49
methods for debugging
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:299
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:298
#define NULL
Definition: def.h:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#define COPYSIGN
Definition: def.h:257
#define SCIP_Longint
Definition: def.h:157
#define SCIP_MAXTREEDEPTH
Definition: def.h:315
#define SCIP_REAL_MAX
Definition: def.h:173
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:242
#define MAX3(x, y, z)
Definition: def.h:246
#define SCIP_Real
Definition: def.h:172
#define ABS(x)
Definition: def.h:234
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL_ABORT(x)
Definition: def.h:352
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define MIN3(x, y, z)
Definition: def.h:250
#define SCIPABORT()
Definition: def.h:345
#define REALABS(x)
Definition: def.h:196
#define EPSGT(x, y, eps)
Definition: def.h:200
#define SCIP_CALL(x)
Definition: def.h:373
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_RETCODE SCIPincludeConsUpgradeNonlinear(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nlconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts)
SCIP_Real SCIPgetRhsNonlinear(SCIP_CONS *cons)
SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
#define SCIP_DECL_LINCONSUPGD(x)
Definition: cons_linear.h:120
SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
SCIP_RETCODE SCIPcleanupConssLinear(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_Real SCIPgetFeasibilityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip_copy.c:2068
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip_copy.c:660
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip_copy.c:711
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:606
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip_general.c:643
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:734
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:390
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2220
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1668
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2172
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3089
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1268
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2843
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3043
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2349
#define SCIPhashFour(a, b, c, d)
Definition: pub_misc.h:556
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2582
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2299
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2611
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2807
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2680
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2550
#define SCIPhashSignature64(a)
Definition: pub_misc.h:549
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip_prob.c:3697
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3475
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:3586
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3229
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3394
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsgPrint
Definition: scip_message.h:79
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:88
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9124
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9376
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9397
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9827
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11215
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:83
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:139
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:57
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:269
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10399
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:428
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4656
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:808
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4227
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4613
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:540
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip_cons.c:396
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:831
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip_cons.c:235
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:281
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip_cons.c:181
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip_cons.c:693
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
Definition: scip_cons.c:900
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:323
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5140
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4636
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4197
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip_cons.c:420
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:516
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:941
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
Definition: scip_cons.c:924
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip_cons.c:468
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip_cons.c:762
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:624
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip_cons.c:444
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4217
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:647
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4670
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:854
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4593
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip_cons.c:670
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:785
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8244
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:8224
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8473
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8234
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8383
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2537
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8665
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip_cons.c:1297
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8423
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8513
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8413
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8343
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8523
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8563
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip_cons.c:1272
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition: scip_cons.c:1322
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition: cons.c:8607
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8403
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2043
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8275
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip_cons.c:998
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8433
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8453
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8573
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8214
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8553
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1813
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2015
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8463
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip_cons.c:1525
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8493
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1174
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip_cons.c:1372
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition: scip_cons.c:1347
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8393
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1785
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8483
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:250
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c:104
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:324
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1030
SCIP_VARTYPE SCIPeventGetNewtype(SCIP_EVENT *event)
Definition: event.c:1283
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:354
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:400
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1218
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1053
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1242
SCIP_VARTYPE SCIPeventGetOldtype(SCIP_EVENT *event)
Definition: event.c:1266
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:3860
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1453
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1552
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1431
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:3870
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1567
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:416
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:83
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:105
SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:424
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:396
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip_nlp.c:1058
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition: nlp.c:1956
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition: scip_nlp.c:954
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:97
void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
Definition: cons.c:8108
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition: cons.c:8076
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17411
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1583
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1422
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1701
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2212
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2167
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1562
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17325
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1607
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17523
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_lp.c:1727
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17312
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2144
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1213
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:137
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
int SCIPgetNSepaRounds(SCIP *scip)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
int SCIPgetNRuns(SCIP *scip)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Real SCIPgetHugeValue(SCIP *scip)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip_tree.c:146
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17619
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:12773
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17639
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17914
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:17881
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18189
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17893
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17747
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17598
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:17537
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3353
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17833
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip_var.c:8688
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18143
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8721
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17560
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip_var.c:8524
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5738
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17925
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17821
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:17583
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:18087
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17757
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:17767
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17418
SCIP_RETCODE SCIPmultiaggregateVar(SCIP *scip, SCIP_VAR *var, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: scip_var.c:8658
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18679
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:17609
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:17857
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17845
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:17629
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18133
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17573
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17705
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17903
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:17547
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18077
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:11941
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:18669
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3295
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:1439
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1214
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition: scip_var.c:8752
SCIP_RETCODE SCIPinferVarFixCons(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5555
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17869
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17809
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:5743
static const char * paramname[]
Definition: lpi_msk.c:5096
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
public methods for conflict analysis handlers
public methods for managing constraints
public methods for managing events
public functions to work with algebraic expressions
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPstatisticMessage
Definition: pub_message.h:123
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
#define SCIPdebugMessage
Definition: pub_message.h:96
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for problem variables
public methods for branching rule plugins and branching
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for cuts and aggregation rows
public methods for event handler plugins and event handlers
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
SCIP_DECL_LINCONSUPGD((*linconsupgd))
structs for symmetry computations
methods for dealing with symmetry detection graphs
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:60
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:64
@ SCIP_LINCONSTYPE_BINPACKING
Definition: type_cons.h:85
@ SCIP_LINCONSTYPE_VARBOUND
Definition: type_cons.h:78
@ SCIP_LINCONSTYPE_EMPTY
Definition: type_cons.h:73
@ SCIP_LINCONSTYPE_INVKNAPSACK
Definition: type_cons.h:83
@ SCIP_LINCONSTYPE_PRECEDENCE
Definition: type_cons.h:77
@ SCIP_LINCONSTYPE_AGGREGATION
Definition: type_cons.h:76
@ SCIP_LINCONSTYPE_MIXEDBINARY
Definition: type_cons.h:88
@ SCIP_LINCONSTYPE_SINGLETON
Definition: type_cons.h:75
@ SCIP_LINCONSTYPE_SETCOVERING
Definition: type_cons.h:81
@ SCIP_LINCONSTYPE_EQKNAPSACK
Definition: type_cons.h:84
@ SCIP_LINCONSTYPE_FREE
Definition: type_cons.h:74
@ SCIP_LINCONSTYPE_KNAPSACK
Definition: type_cons.h:86
@ SCIP_LINCONSTYPE_SETPARTITION
Definition: type_cons.h:79
@ SCIP_LINCONSTYPE_INTKNAPSACK
Definition: type_cons.h:87
@ SCIP_LINCONSTYPE_SETPACKING
Definition: type_cons.h:80
@ SCIP_LINCONSTYPE_GENERAL
Definition: type_cons.h:89
@ SCIP_LINCONSTYPE_CARDINALITY
Definition: type_cons.h:82
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition: type_cons.h:91
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:125
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:73
#define SCIP_EVENTTYPE_TYPECHANGED
Definition: type_event.h:86
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:76
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:120
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:79
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:72
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:71
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:152
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:75
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:124
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:121
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:122
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:151
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:123
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:77
@ SCIP_EXPRCURV_LINEAR
Definition: type_expr.h:65
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:57
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
@ SCIP_VERBLEVEL_HIGH
Definition: type_message.h:56
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_FEASIBLE
Definition: type_result.h:45
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_CONSADDED
Definition: type_result.h:52
@ SCIP_SEPARATED
Definition: type_result.h:49
@ SCIP_SUCCESS
Definition: type_result.h:58
@ SCIP_INFEASIBLE
Definition: type_result.h:46
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_READERROR
Definition: type_retcode.h:45
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PROBLEM
Definition: type_set.h:45
@ SCIP_STAGE_INITSOLVE
Definition: type_set.h:52
@ SCIP_STAGE_EXITPRESOLVE
Definition: type_set.h:50
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition: type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition: type_set.h:51
enum SYM_Symtype SYM_SYMTYPE
Definition: type_symmetry.h:64
@ SYM_SYMTYPE_SIGNPERM
Definition: type_symmetry.h:62
@ SYM_SYMTYPE_PERM
Definition: type_symmetry.h:61
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:54
#define NLOCKTYPES
Definition: type_var.h:94
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:63
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_IMPLINT
Definition: type_var.h:64
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:62
@ SCIP_VARSTATUS_ORIGINAL
Definition: type_var.h:49
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:52
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:51
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:54
@ SCIP_VARSTATUS_NEGATED
Definition: type_var.h:55
@ SCIP_VARSTATUS_AGGREGATED
Definition: type_var.h:53
@ SCIP_VARSTATUS_LOOSE
Definition: type_var.h:50
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:100
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:97
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:57