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 */
6797 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight )
6798 {
6799 SCIP_Real newub;
6800
6801 newub = (rhs - minresactivity)/val;
6802
6803 if( !SCIPisInfinity(scip, newub) &&
6804 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6805 {
6806 SCIP_Bool activityunreliable;
6807 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6808
6809 /* check minresactivities for reliability */
6810 if( activityunreliable )
6811 {
6812 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6813 newub = (rhs - minresactivity)/val;
6814 activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6815 (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6816 && (!force || !SCIPisLT(scip, newub, ub)));
6817 }
6818
6819 if( !activityunreliable )
6820 {
6821 /* tighten upper bound */
6822 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6823 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6824 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6825 &infeasible, &tightened) );
6826 if( infeasible )
6827 {
6828 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6829 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6830
6831 /* analyze conflict */
6833
6834 *cutoff = TRUE;
6835 return SCIP_OKAY;
6836 }
6837 if( tightened )
6838 {
6839 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6840 assert(SCIPisFeasLE(scip, ub, newub));
6841 (*nchgbds)++;
6842
6843 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6844 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6845 }
6846 }
6847 }
6848 }
6849
6850 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight )
6851 {
6852 SCIP_Real newlb;
6853
6854 newlb = (lhs - maxresactivity)/val;
6855 if( !SCIPisInfinity(scip, -newlb) &&
6856 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6857 {
6858 /* check maxresactivities for reliability */
6859 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6860 {
6861 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6862 newlb = (lhs - maxresactivity)/val;
6863
6864 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6865 && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6866 && (!force || !SCIPisGT(scip, newlb, lb))) )
6867 return SCIP_OKAY;
6868 }
6869
6870 /* tighten lower bound */
6871 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6872 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6873 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6874 &infeasible, &tightened) );
6875 if( infeasible )
6876 {
6877 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6878 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6879
6880 /* analyze conflict */
6882
6883 *cutoff = TRUE;
6884 return SCIP_OKAY;
6885 }
6886 if( tightened )
6887 {
6888 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6889 assert(SCIPisFeasGE(scip, lb, newlb));
6890 (*nchgbds)++;
6891 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6892 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6893 }
6894 }
6895 }
6896 }
6897 else
6898 {
6899 /* check, if we can tighten the variable's bounds */
6900 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight )
6901 {
6902 SCIP_Real newlb;
6903
6904 newlb = (rhs - minresactivity)/val;
6905 if( !SCIPisInfinity(scip, -newlb) &&
6906 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6907 {
6908 SCIP_Bool activityunreliable;
6909 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6910 /* check minresactivities for reliability */
6911 if( activityunreliable )
6912 {
6913 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6914 newlb = (rhs - minresactivity)/val;
6915
6916 activityunreliable = SCIPisInfinity(scip, -minresactivity)
6917 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6918 && (!force || !SCIPisGT(scip, newlb, lb)));
6919 }
6920
6921 if( !activityunreliable )
6922 {
6923 /* tighten lower bound */
6924 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6925 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6926 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6927 &infeasible, &tightened) );
6928 if( infeasible )
6929 {
6930 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6931 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6932
6933 /* analyze conflict */
6935
6936 *cutoff = TRUE;
6937 return SCIP_OKAY;
6938 }
6939 if( tightened )
6940 {
6941 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6942 assert(SCIPisFeasGE(scip, lb, newlb));
6943 (*nchgbds)++;
6944 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6945 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6946 }
6947 }
6948 }
6949 }
6950
6951 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight )
6952 {
6953 SCIP_Real newub;
6954
6955 newub = (lhs - maxresactivity)/val;
6956 if( !SCIPisInfinity(scip, newub) &&
6957 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6958 {
6959 /* check maxresactivities for reliability */
6960 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6961 {
6962 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6963 newub = (lhs - maxresactivity)/val;
6964
6965 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6966 && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6967 && (!force || !SCIPisLT(scip, newub, ub))) )
6968 return SCIP_OKAY;
6969 }
6970
6971 /* tighten upper bound */
6972 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6973 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6974 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6975 &infeasible, &tightened) );
6976 if( infeasible )
6977 {
6978 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6979 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6980
6981 /* analyze conflict */
6983
6984 *cutoff = TRUE;
6985 return SCIP_OKAY;
6986 }
6987 if( tightened )
6988 {
6989 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6990 assert(SCIPisFeasLE(scip, ub, newub));
6991 (*nchgbds)++;
6992 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6993 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6994 }
6995 }
6996 }
6997 }
6998
6999 return SCIP_OKAY;
7000}
7001
7002#define MAXTIGHTENROUNDS 10
7003
7004/** tightens bounds of variables in constraint due to activity bounds */
7005static
7007 SCIP* scip, /**< SCIP data structure */
7008 SCIP_CONS* cons, /**< linear constraint */
7009 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7010 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7011 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7012 int* nchgbds /**< pointer to count the total number of tightened bounds */
7013 )
7014{
7015 SCIP_CONSDATA* consdata;
7016 unsigned int tightenmode;
7017 int nvars;
7018 int nrounds;
7019 int lastchange;
7020 int oldnchgbds;
7021#ifndef SCIP_DEBUG
7022 int oldnchgbdstotal;
7023#endif
7024 int v;
7025 SCIP_Bool force;
7026 SCIP_Bool easycase;
7027
7028 assert(scip != NULL);
7029 assert(cons != NULL);
7030 assert(nchgbds != NULL);
7031 assert(cutoff != NULL);
7032
7033 *cutoff = FALSE;
7034
7035 /* we cannot tighten variables' bounds, if the constraint may be not complete */
7036 if( SCIPconsIsModifiable(cons) )
7037 return SCIP_OKAY;
7038
7039 /* if a constraint was created after presolve, then it may hold fixed variables
7040 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7041 * thus, ensure here again that variable fixings have been applied
7042 */
7043 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7044 if( *cutoff )
7045 return SCIP_OKAY;
7046
7047 /* check if constraint has any chances of tightening bounds */
7048 if( !canTightenBounds(cons) )
7049 return SCIP_OKAY;
7050
7051 consdata = SCIPconsGetData(cons);
7052 assert(consdata != NULL);
7053
7054 nvars = consdata->nvars;
7055 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7056
7057 /* we are at the root node or during presolving */
7058 if( SCIPgetDepth(scip) < 1 )
7059 tightenmode = 2;
7060 else
7061 tightenmode = 1;
7062
7063 /* stop if we already tightened the constraint and the tightening is not forced */
7064 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7065 return SCIP_OKAY;
7066
7067 /* ensure that the variables are properly sorted */
7068 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7069 {
7070 SCIP_CALL( consdataSort(scip, consdata) );
7071 assert(consdata->coefsorted);
7072 }
7073
7074 /* update maximal activity delta if necessary */
7075 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7077
7078 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7079 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7080 checkMaxActivityDelta(scip, consdata);
7081
7082 /* this may happen if all variables are fixed */
7083 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7084 return SCIP_OKAY;
7085
7086 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7087 {
7088 SCIP_Real slack;
7089 SCIP_Real surplus;
7090 SCIP_Real minactivity;
7091 SCIP_Real maxactivity;
7092 SCIP_Bool ismintight;
7093 SCIP_Bool ismaxtight;
7094 SCIP_Bool isminsettoinfinity;
7095 SCIP_Bool ismaxsettoinfinity;
7096
7097 /* use maximal activity delta to skip propagation (cannot deduce anything) */
7098 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &ismintight, &ismaxtight,
7099 &isminsettoinfinity, &ismaxsettoinfinity);
7100 assert(!SCIPisInfinity(scip, minactivity));
7101 assert(!SCIPisInfinity(scip, -maxactivity));
7102
7103 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7104 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7105
7106 /* check if the constraint will propagate */
7107 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7108 return SCIP_OKAY;
7109 }
7110
7111 /* check if we can use fast implementation for easy and numerically well behaved cases */
7112 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7113
7114 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7115 lastchange = -1;
7116 oldnchgbds = 0;
7117
7118#ifndef SCIP_DEBUG
7119 oldnchgbdstotal = *nchgbds;
7120#endif
7121
7122 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7123 {
7124 /* ensure that the variables are properly sorted
7125 *
7126 * note: it might happen that integer variables become binary during bound tightening at the root node
7127 */
7128 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7129 {
7130 SCIP_CALL( consdataSort(scip, consdata) );
7131 assert(consdata->coefsorted);
7132 }
7133
7134 /* mark the constraint to have the variables' bounds tightened */
7135 consdata->boundstightened = (unsigned int)tightenmode;
7136
7137 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7138 * sorting enables skipping variables
7139 */
7140 v = 0;
7141 while( v < nvars && v != lastchange && !(*cutoff) )
7142 {
7143 oldnchgbds = *nchgbds;
7144
7145 if( easycase )
7146 {
7147 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7148 }
7149 else
7150 {
7151 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7152 }
7153
7154 /* if there was no progress, skip the rest of the binary variables */
7155 if( *nchgbds > oldnchgbds )
7156 {
7157 lastchange = v;
7158 ++v;
7159 }
7160 else if( consdata->coefsorted && v < consdata->nbinvars - 1
7161 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7162 v = consdata->nbinvars;
7163 else
7164 ++v;
7165 }
7166
7167#ifndef SCIP_DEBUG
7168 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7169 *nchgbds - oldnchgbdstotal, nrounds);
7170 oldnchgbdstotal += oldnchgbds;
7171#endif
7172 }
7173
7174#ifndef NDEBUG
7175 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7176 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7177#endif
7178
7179 return SCIP_OKAY;
7180}
7181
7182/** checks linear constraint for feasibility of given solution or current solution */
7183static
7185 SCIP* scip, /**< SCIP data structure */
7186 SCIP_CONS* cons, /**< linear constraint */
7187 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7188 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7189 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7190 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7191 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7192 )
7193{
7194 SCIP_CONSDATA* consdata;
7195 SCIP_Real activity;
7196 SCIP_Real absviol;
7197 SCIP_Real relviol;
7198 SCIP_Real lhsviol;
7199 SCIP_Real rhsviol;
7200
7201 assert(scip != NULL);
7202 assert(cons != NULL);
7203 assert(violated != NULL);
7204
7205 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7207
7208 consdata = SCIPconsGetData(cons);
7209 assert(consdata != NULL);
7210
7211 *violated = FALSE;
7212
7213 if( consdata->row != NULL )
7214 {
7215 if( !checklprows && SCIProwIsInLP(consdata->row) )
7216 return SCIP_OKAY;
7217 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7218 activity = consdataComputePseudoActivity(scip, consdata);
7219 else
7220 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7221 }
7222 else
7223 activity = consdataGetActivity(scip, consdata, sol);
7224
7225 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7226 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7227 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7228 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7229
7230 /* calculate absolute and relative bound violations */
7231 lhsviol = consdata->lhs - activity;
7232 rhsviol = activity - consdata->rhs;
7233
7234 absviol = 0.0;
7235 relviol = 0.0;
7236 if( (lhsviol > 0) && (lhsviol > rhsviol) )
7237 {
7238 absviol = lhsviol;
7239 relviol = SCIPrelDiff(consdata->lhs, activity);
7240 }
7241 else if( rhsviol > 0 )
7242 {
7243 absviol = rhsviol;
7244 relviol = SCIPrelDiff(activity, consdata->rhs);
7245 }
7246
7247 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7248 * return infeasible for safety
7249 */
7250 if( activity == SCIP_INVALID ) /*lint !e777*/
7251 {
7252 assert(sol == NULL);
7253 *violated = TRUE;
7254
7255 /* set violation of invalid pseudo solutions */
7256 absviol = SCIP_INVALID;
7257 relviol = SCIP_INVALID;
7258
7259 /* reset constraint age since we are in enforcement */
7261 }
7262 /* check with relative tolerances (the default) */
7263 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7264 {
7265 /* the "normal" check: one of the two sides is violated */
7266 if( !checkrelmaxabs )
7267 {
7268 *violated = TRUE;
7269
7270 /* only reset constraint age if we are in enforcement */
7271 if( sol == NULL )
7272 {
7274 }
7275 }
7276 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7277 * small compared to the absolute values occurring in the activity
7278 */
7279 else
7280 {
7281 SCIP_Real maxabs;
7282 SCIP_Real coef;
7283 SCIP_Real absval;
7284 SCIP_Real solval;
7285 int v;
7286
7287 maxabs = 1.0;
7288
7289 /* compute maximum absolute value */
7290 for( v = 0; v < consdata->nvars; ++v )
7291 {
7292 if( consdata->vals != NULL )
7293 {
7294 coef = consdata->vals[v];
7295 }
7296 else
7297 coef = 1.0;
7298
7299 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7300 absval = REALABS( coef * solval );
7301 maxabs = MAX( maxabs, absval );
7302 }
7303
7304 /* regard left hand side, first */
7305 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7306 {
7307 /* check whether violation is random noise */
7308 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7309 {
7310 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7311 consdata->lhs - activity, maxabs);
7312 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7313
7314 /* only increase constraint age if we are in enforcement */
7315 if( sol == NULL )
7316 {
7317 SCIP_CALL( SCIPincConsAge(scip, cons) );
7318 }
7319 }
7320 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7321 else if( SCIPisZero(scip, consdata->lhs) )
7322 {
7323 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7324 {
7325 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7326 consdata->lhs - activity, maxabs);
7327 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7328
7329 /* only increase constraint age if we are in enforcement */
7330 if( sol == NULL )
7331 {
7332 SCIP_CALL( SCIPincConsAge(scip, cons) );
7333 }
7334 }
7335 else
7336 {
7337 *violated = TRUE;
7338
7339 /* only reset constraint age if we are in enforcement */
7340 if( sol == NULL )
7341 {
7343 }
7344 }
7345 }
7346 else
7347 {
7348 *violated = TRUE;
7349
7350 /* only reset constraint age if we are in enforcement */
7351 if( sol == NULL )
7352 {
7354 }
7355 }
7356 }
7357
7358 /* now regard right hand side */
7359 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7360 {
7361 /* check whether violation is random noise */
7362 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7363 {
7364 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7365 activity - consdata->rhs, maxabs);
7366 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7367
7368 /* only increase constraint age if we are in enforcement */
7369 if( sol == NULL )
7370 {
7371 SCIP_CALL( SCIPincConsAge(scip, cons) );
7372 }
7373 }
7374 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7375 else if( SCIPisZero(scip, consdata->rhs) )
7376 {
7377 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7378 {
7379 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7380 activity - consdata->rhs, maxabs);
7381 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7382
7383 /* only increase constraint age if we are in enforcement */
7384 if( sol == NULL )
7385 {
7386 SCIP_CALL( SCIPincConsAge(scip, cons) );
7387 }
7388 }
7389 else
7390 {
7391 *violated = TRUE;
7392
7393 /* only reset constraint age if we are in enforcement */
7394 if( sol == NULL )
7395 {
7397 }
7398 }
7399 }
7400 else
7401 {
7402 *violated = TRUE;
7403
7404 /* only reset constraint age if we are in enforcement */
7405 if( sol == NULL )
7406 {
7408 }
7409 }
7410 }
7411 }
7412 }
7413 /* check with absolute tolerances */
7414 else if( consdata->checkabsolute &&
7415 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7416 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7417 {
7418 *violated = TRUE;
7419
7420 /* only reset constraint age if we are in enforcement */
7421 if( sol == NULL )
7422 {
7424 }
7425 }
7426 else
7427 {
7428 /* only increase constraint age if we are in enforcement */
7429 if( sol == NULL )
7430 {
7431 SCIP_CALL( SCIPincConsAge(scip, cons) );
7432 }
7433 }
7434
7435 /* update absolute and relative violation of the solution */
7436 if( sol != NULL )
7437 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7438
7439 return SCIP_OKAY;
7440}
7441
7442/** creates an LP row in a linear constraint data */
7443static
7445 SCIP* scip, /**< SCIP data structure */
7446 SCIP_CONS* cons /**< linear constraint */
7447 )
7448{
7449 SCIP_CONSDATA* consdata;
7450
7451 assert(scip != NULL);
7452 assert(cons != NULL);
7453
7454 consdata = SCIPconsGetData(cons);
7455 assert(consdata != NULL);
7456 assert(consdata->row == NULL);
7457
7458 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7460
7461 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7462
7463 return SCIP_OKAY;
7464}
7465
7466/** adds linear constraint as cut to the LP */
7467static
7469 SCIP* scip, /**< SCIP data structure */
7470 SCIP_CONS* cons, /**< linear constraint */
7471 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7472 )
7473{
7474 SCIP_CONSDATA* consdata;
7475
7476 assert(scip != NULL);
7477 assert(cons != NULL);
7478
7479 consdata = SCIPconsGetData(cons);
7480 assert(consdata != NULL);
7481
7482 if( consdata->row == NULL )
7483 {
7484 if( !SCIPconsIsModifiable(cons) )
7485 {
7486 /* 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
7487 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7488 */
7489 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7490 if( *cutoff )
7491 return SCIP_OKAY;
7492 }
7493
7494 /* convert consdata object into LP row */
7495 SCIP_CALL( createRow(scip, cons) );
7496 }
7497 assert(consdata->row != NULL);
7498
7499 if( consdata->nvars == 0 )
7500 {
7501 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7502 }
7503
7504 /* insert LP row as cut */
7505 if( !SCIProwIsInLP(consdata->row) )
7506 {
7507 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7508 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7509 /* if presolving is turned off, the row might be trivial */
7510 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7511 {
7512 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7513 }
7514#ifndef NDEBUG
7515 else
7516 {
7517 int pr;
7518 int cr;
7519 SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7520 SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7521 assert( pr == 0 || cr == 0 );
7522 }
7523#endif
7524 }
7525
7526 return SCIP_OKAY;
7527}
7528
7529/** adds linear constraint as row to the NLP, if not added yet */
7530static
7532 SCIP* scip, /**< SCIP data structure */
7533 SCIP_CONS* cons /**< linear constraint */
7534 )
7535{
7536 SCIP_CONSDATA* consdata;
7537
7538 assert(SCIPisNLPConstructed(scip));
7539
7540 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7541 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7542 return SCIP_OKAY;
7543
7544 consdata = SCIPconsGetData(cons);
7545 assert(consdata != NULL);
7546
7547 if( consdata->nlrow == NULL )
7548 {
7549 assert(consdata->lhs <= consdata->rhs);
7550
7551 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7552 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7553
7554 assert(consdata->nlrow != NULL);
7555 }
7556
7557 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7558 {
7559 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7560 }
7561
7562 return SCIP_OKAY;
7563}
7564
7565/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7566static
7568 SCIP* scip, /**< SCIP data structure */
7569 SCIP_CONS* cons, /**< linear constraint */
7570 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7571 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7572 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7573 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7574 * the ones with non-zero dual value? */
7575 int* ncuts, /**< pointer to add up the number of found cuts */
7576 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7577 )
7578{
7579 SCIP_CONSDATA* consdata;
7580 SCIP_Bool violated;
7581 int oldncuts;
7582
7583 assert(scip != NULL);
7584 assert(conshdlrdata != NULL);
7585 assert(cons != NULL);
7586 assert(cutoff != NULL);
7587
7588 consdata = SCIPconsGetData(cons);
7589 assert(ncuts != NULL);
7590 assert(consdata != NULL);
7591
7592 oldncuts = *ncuts;
7593 *cutoff = FALSE;
7594
7595 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7596
7597 if( violated )
7598 {
7599 /* insert LP row as cut */
7600 SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7601 (*ncuts)++;
7602 }
7603 else if( !SCIPconsIsModifiable(cons) && separatecards )
7604 {
7605 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7606 if( !separateall && sol == NULL )
7607 {
7608 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7609 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7610 {
7611 SCIP_Real dualsol;
7612
7613 dualsol = SCIProwGetDualsol(consdata->row);
7614 if( SCIPisFeasNegative(scip, dualsol) )
7615 {
7616 if( !SCIPisInfinity(scip, consdata->rhs) )
7617 {
7618 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7619 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7620 }
7621 }
7622 else if( SCIPisFeasPositive(scip, dualsol) )
7623 {
7624 if( !SCIPisInfinity(scip, -consdata->lhs) )
7625 {
7626 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7627 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7628 }
7629 }
7630 }
7631 }
7632 else
7633 {
7634 if( !SCIPisInfinity(scip, consdata->rhs) )
7635 {
7636 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7637 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7638 }
7639 if( !SCIPisInfinity(scip, -consdata->lhs) )
7640 {
7641 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7642 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7643 }
7644 }
7645 }
7646
7647 if( *ncuts > oldncuts )
7648 {
7650 }
7651
7652 return SCIP_OKAY;
7653}
7654
7655/** propagation method for linear constraints */
7656static
7658 SCIP* scip, /**< SCIP data structure */
7659 SCIP_CONS* cons, /**< linear constraint */
7660 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7661 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7662 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7663 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7664 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7665 int* nchgbds /**< pointer to count the total number of tightened bounds */
7666 )
7667{
7668 SCIP_CONSDATA* consdata;
7669 SCIP_Real minactivity;
7670 SCIP_Real maxactivity;
7671 SCIP_Bool isminacttight;
7672 SCIP_Bool ismaxacttight;
7673 SCIP_Bool isminsettoinfinity;
7674 SCIP_Bool ismaxsettoinfinity;
7675
7676 assert(scip != NULL);
7677 assert(cons != NULL);
7678 assert(cutoff != NULL);
7679 assert(nchgbds != NULL);
7680
7681 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7682
7683 consdata = SCIPconsGetData(cons);
7684 assert(consdata != NULL);
7685
7686 if( consdata->eventdata == NULL )
7687 {
7688 SCIP_CONSHDLR* conshdlr;
7689 SCIP_CONSHDLRDATA* conshdlrdata;
7690
7691 conshdlr = SCIPconsGetHdlr(cons);
7692 assert(conshdlr != NULL);
7693
7694 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7695 assert(conshdlrdata != NULL);
7696
7697 /* catch bound change events of variables */
7698 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7699 assert(consdata->eventdata != NULL);
7700 }
7701
7702 *cutoff = FALSE;
7703
7704 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7705 if( !SCIPconsIsModifiable(cons) )
7706 {
7707 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7709 {
7710 SCIP_CALL( SCIPincConsAge(scip, cons) );
7711 }
7712
7713 /* tighten the variable's bounds */
7714 if( tightenbounds )
7715 {
7716 int oldnchgbds;
7717
7718 oldnchgbds = *nchgbds;
7719
7720 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7721
7722 if( *nchgbds > oldnchgbds )
7723 {
7725 }
7726 }
7727
7728 /* propagate ranged rows */
7729 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7730 {
7731 int nfixedvars;
7732 int naddconss;
7733 SCIPdebug( int oldnchgbds = *nchgbds; )
7734
7735 nfixedvars = 0;
7736 naddconss = 0;
7737
7738 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7739
7740 if( *cutoff )
7741 {
7742 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7743 }
7744 else
7745 {
7746 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7747 }
7748
7749 if( nfixedvars > 0 )
7750 *nchgbds += 2*nfixedvars;
7751 } /*lint !e438*/
7752
7753 /* check constraint for infeasibility and redundancy */
7754 if( !(*cutoff) )
7755 {
7756 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
7757 &isminsettoinfinity, &ismaxsettoinfinity);
7758
7759 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7760 {
7761 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7762 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7763
7764 /* analyze conflict */
7766
7768 *cutoff = TRUE;
7769 }
7770 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7771 {
7772 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7773 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7774
7775 /* analyze conflict */
7777
7779 *cutoff = TRUE;
7780 }
7781 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7782 {
7783 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7784 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7785
7786 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7787 if( consdata->nvars > 0 )
7789 else
7790 SCIP_CALL( SCIPdelCons(scip, cons) );
7791 }
7792 }
7793 }
7794
7795 return SCIP_OKAY;
7796}
7797
7798
7799/*
7800 * Presolving methods
7801 */
7802
7803/** converts all variables with fixed domain into FIXED variables */
7804static
7806 SCIP* scip, /**< SCIP data structure */
7807 SCIP_CONS* cons, /**< linear constraint */
7808 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7809 int* nfixedvars /**< pointer to count the total number of fixed variables */
7810 )
7811{
7812 SCIP_CONSDATA* consdata;
7813 SCIP_VAR* var;
7814 SCIP_VARSTATUS varstatus;
7815 SCIP_Real lb;
7816 SCIP_Real ub;
7817 SCIP_Bool fixed;
7818 SCIP_Bool infeasible;
7819 int v;
7820
7821 assert(scip != NULL);
7822 assert(cons != NULL);
7823 assert(cutoff != NULL);
7824 assert(nfixedvars != NULL);
7825
7826 consdata = SCIPconsGetData(cons);
7827 assert(consdata != NULL);
7828
7829 for( v = 0; v < consdata->nvars; ++v )
7830 {
7831 assert(consdata->vars != NULL);
7832 var = consdata->vars[v];
7833 varstatus = SCIPvarGetStatus(var);
7834
7835 if( varstatus != SCIP_VARSTATUS_FIXED )
7836 {
7837 lb = SCIPvarGetLbGlobal(var);
7838 ub = SCIPvarGetUbGlobal(var);
7839 if( SCIPisEQ(scip, lb, ub) )
7840 {
7841 SCIP_Real fixval;
7842
7843 fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7844 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7845 SCIPvarGetName(var), lb, ub, fixval);
7846 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7847 if( infeasible )
7848 {
7849 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7850 *cutoff = TRUE;
7851 return SCIP_OKAY;
7852 }
7853 if( fixed )
7854 (*nfixedvars)++;
7855 }
7856 }
7857 }
7858
7859 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7860
7861 if( infeasible )
7862 {
7863 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7864 *cutoff = TRUE;
7865 return SCIP_OKAY;
7866 }
7867
7868 assert(consdata->removedfixings);
7869
7870 return SCIP_OKAY;
7871}
7872
7873#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7874
7875/** extracts cliques of the constraint and adds them to SCIP
7876 *
7877 * The following clique extraction mechanism are implemeneted
7878 *
7879 * 1. collect binary variables and sort them in non increasing order, then
7880 *
7881 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7882 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7883 * condition
7884 *
7885 * minactivity + vals[i] + vals[i+1] > rhs
7886 *
7887 * and also add the binary to binary implication also for non-successive variables for which the same argument
7888 * holds
7889 *
7890 * minactivity + vals[i] + vals[j] > rhs
7891 *
7892 * 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
7893 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7894 *
7895 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7896 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7897 * condition
7898 *
7899 * maxactivity + vals[i] + vals[i-1] < lhs
7900 *
7901 * and also add the binary to binary implication also for non-successive variables for which the same argument
7902 * holds
7903 *
7904 * maxactivity + vals[i] + vals[j] < lhs
7905 *
7906 * e.g. you could multiply the above example by -1
7907 *
7908 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7909 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7910 * condition
7911 *
7912 * minactivity - vals[i] - vals[i-1] > rhs
7913 *
7914 * and also add the binary to binary implication also for non-successive variables for which the
7915 * same argument holds
7916 *
7917 * minactivity - vals[i] - vals[j] > rhs
7918 *
7919 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7920 * implication x1 = 0 => x3 = 1
7921 *
7922 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7923 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7924 * condition
7925 *
7926 * maxactivity - vals[i] - vals[i+1] < lhs
7927 *
7928 * and also add the binary to binary implication also for non-successive variables for which the same argument
7929 * holds
7930 *
7931 * maxactivity - vals[i] - vals[j] < lhs
7932 *
7933 * e.g. you could multiply the above example by -1
7934 *
7935 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7936 * as clique, (this part is done at the end of the method)
7937 *
7938 */
7939static
7941 SCIP* scip, /**< SCIP data structure */
7942 SCIP_CONS* cons, /**< linear constraint */
7943 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7944 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7945 int* nfixedvars, /**< pointer to count number of fixed variables */
7946 int* nchgbds, /**< pointer to count the total number of tightened bounds */
7947 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7948 )
7949{
7950 SCIP_VAR** vars;
7951 SCIP_Real* vals;
7952 SCIP_CONSDATA* consdata;
7953 SCIP_Bool lhsclique;
7954 SCIP_Bool rhsclique;
7955 SCIP_Bool finitelhs;
7956 SCIP_Bool finiterhs;
7957 SCIP_Bool finiteminact;
7958 SCIP_Bool finitemaxact;
7959 SCIP_Bool finitenegminact;
7960 SCIP_Bool finitenegmaxact;
7961 SCIP_Bool finiteposminact;
7962 SCIP_Bool finiteposmaxact;
7963 SCIP_Bool infeasible;
7964 SCIP_Bool stopped;
7965 int cliquenonzerosadded;
7966 int v;
7967 int i;
7968 int nposcoefs;
7969 int nnegcoefs;
7970 int nvars;
7971
7972 assert(scip != NULL);
7973 assert(cons != NULL);
7974 assert(nfixedvars != NULL);
7975 assert(nchgbds != NULL);
7976 assert(cutoff != NULL);
7977 assert(!SCIPconsIsDeleted(cons));
7978
7979 consdata = SCIPconsGetData(cons);
7980 assert(consdata != NULL);
7981
7982 if( consdata->nvars < 2 )
7983 return SCIP_OKAY;
7984
7985 /* add implications if possible
7986 *
7987 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7988 * maximal absolute contribution and also only if this variable would force all other variables to their bound
7989 * corresponding to the global minimal activity of the constraint
7990 */
7991 if( !consdata->implsadded )
7992 {
7993 /* sort variables by variable type */
7994 SCIP_CALL( consdataSort(scip, consdata) );
7995
7996 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7997 * up front, might change sorting correspondingly
7998 */
7999 /* fast abort if no binaries seem to exist
8000 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
8001 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
8002 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
8003 * which is the requirement for consdataSort() to actually resort the variables
8004 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
8005 */
8006 if( !SCIPvarIsBinary(consdata->vars[0]) )
8007 return SCIP_OKAY;
8008
8009 nvars = consdata->nvars;
8010 vars = consdata->vars;
8011 vals = consdata->vals;
8012
8013 /* recompute activities if needed */
8014 if( !consdata->validactivities )
8015 consdataCalcActivities(scip, consdata);
8016 assert(consdata->validactivities);
8017
8018 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8019 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8020 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8021 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8022 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8023 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8024 finiteminact = (finitenegminact && finiteposminact);
8025 finitemaxact = (finitenegmaxact && finiteposmaxact);
8026
8027 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8028 {
8029 SCIP_Real maxabscontrib = -1.0;
8030 SCIP_Bool posval = FALSE;
8031 SCIP_Bool allbinary = TRUE;
8032 int oldnchgbds = *nchgbds;
8033 int nbdchgs = 0;
8034 int nimpls = 0;
8035 int position = -1;
8036
8037 /* we need a valid minimal/maximal activity to add cliques */
8038 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8039 {
8041 assert(consdata->validglbminact);
8042 }
8043
8044 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8045 {
8047 assert(consdata->validglbmaxact);
8048 }
8049 assert(consdata->validglbminact || consdata->validglbmaxact);
8050
8051 /* @todo extend this to local/constraint probing */
8052
8053 /* determine maximal contribution to the activity */
8054 for( v = nvars - 1; v >= 0; --v )
8055 {
8056 if( SCIPvarIsBinary(vars[v]) )
8057 {
8058 if( vals[v] > 0 )
8059 {
8060 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8061
8062 if( value > maxabscontrib )
8063 {
8064 maxabscontrib = value;
8065 position = v;
8066 posval = TRUE;
8067 }
8068 }
8069 else
8070 {
8071 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8072
8073 value = REALABS(value);
8074
8075 if( value > maxabscontrib )
8076 {
8077 maxabscontrib = value;
8078 position = v;
8079 posval = FALSE;
8080 }
8081 }
8082 }
8083 else
8084 allbinary = FALSE;
8085 }
8086 assert(0 <= position && position < nvars);
8087
8088 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8089 {
8090 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8091 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8092 * implications
8093 */
8094 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8095 {
8096 for( v = nvars - 1; v >= 0; --v )
8097 {
8098 /* binary to binary implications will be collected when extrating cliques */
8099 if( !SCIPvarIsBinary(vars[v]) )
8100 {
8101 if( v != position )
8102 {
8103 if( vals[v] > 0 )
8104 {
8105 /* add implications */
8106 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8107 ++nimpls;
8108 *nchgbds += nbdchgs;
8109 }
8110 else
8111 {
8112 /* add implications */
8113 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8114 ++nimpls;
8115 *nchgbds += nbdchgs;
8116 }
8117
8118 if( infeasible )
8119 {
8120 *cutoff = TRUE;
8121 break;
8122 }
8123 }
8124 }
8125 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8126 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8127 break;
8128 }
8129 }
8130
8131 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8132 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8133 * implications
8134 */
8135 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8136 {
8137 for( v = nvars - 1; v >= 0; --v )
8138 {
8139 /* binary to binary implications will be collected when extrating cliques */
8140 if( !SCIPvarIsBinary(vars[v]) )
8141 {
8142 if( v != position )
8143 {
8144 if( vals[v] > 0 )
8145 {
8146 /* add implications */
8147 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8148 ++nimpls;
8149 *nchgbds += nbdchgs;
8150 }
8151 else
8152 {
8153 /* add implications */
8154 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8155 ++nimpls;
8156 *nchgbds += nbdchgs;
8157 }
8158
8159 if( infeasible )
8160 {
8161 *cutoff = TRUE;
8162 break;
8163 }
8164 }
8165 }
8166 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8167 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8168 break;
8169 }
8170 }
8171
8172 /* did we find some implications */
8173 if( nimpls > 0 )
8174 {
8175 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8176
8177 if( *cutoff )
8178 return SCIP_OKAY;
8179
8180 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8181 if( *nchgbds - oldnchgbds > 0 )
8182 {
8183 /* check for fixed variables */
8184 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8185 if( *cutoff )
8186 return SCIP_OKAY;
8187
8188 /* tighten variable's bounds */
8189 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8190 if( *cutoff )
8191 return SCIP_OKAY;
8192
8193 /* check for fixed variables */
8194 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8195 if( *cutoff )
8196 return SCIP_OKAY;
8197 }
8198 }
8199 }
8200 }
8201
8202 consdata->implsadded = TRUE;
8203 }
8204
8205 /* check if we already added the cliques of this constraint */
8206 if( consdata->cliquesadded )
8207 return SCIP_OKAY;
8208
8209 consdata->cliquesadded = TRUE;
8210 cliquenonzerosadded = 0;
8211 stopped = FALSE;
8212
8213 /* sort variables by variable type */
8214 SCIP_CALL( consdataSort(scip, consdata) );
8215
8216 nvars = consdata->nvars;
8217 vars = consdata->vars;
8218 vals = consdata->vals;
8219
8220 /**@todo extract more cliques, implications and variable bounds from linear constraints */
8221
8222 /* recompute activities if needed */
8223 if( !consdata->validactivities )
8224 consdataCalcActivities(scip, consdata);
8225 assert(consdata->validactivities);
8226
8227 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8228 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8229 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8230 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8231 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8232 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8233 finiteminact = (finitenegminact && finiteposminact);
8234 finitemaxact = (finitenegmaxact && finiteposmaxact);
8235
8236 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8237 * information
8238 */
8239 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8240 {
8241 SCIP_VAR** binvars;
8242 SCIP_Real* binvarvals;
8243 int nposbinvars = 0;
8244 int nnegbinvars = 0;
8245 int allonebinary = 0;
8246
8247 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8248 SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8249
8250 /* collect binary variables */
8251 for( i = 0; i < nvars; ++i )
8252 {
8253 if( SCIPvarIsBinary(vars[i]) )
8254 {
8255 assert(!SCIPisZero(scip, vals[i]));
8256
8257 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8258 ++allonebinary;
8259
8260 binvars[nposbinvars + nnegbinvars] = vars[i];
8261 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8262
8263 if( SCIPisPositive(scip, vals[i]) )
8264 ++nposbinvars;
8265 else
8266 ++nnegbinvars;
8267
8268 assert(nposbinvars + nnegbinvars <= nvars);
8269 }
8270 /* stop searching for binary variables, because the constraint data is sorted */
8271 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8272 break;
8273 }
8274 assert(nposbinvars + nnegbinvars <= nvars);
8275
8276 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8277 * cliques
8278 */
8279 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8280 {
8281 SCIP_Real threshold;
8282 int oldnchgbds = *nchgbds;
8283 int nbdchgs;
8284 int jstart;
8285 int j;
8286
8287 /* we need a valid minimal/maximal activity to add cliques */
8288 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8289 {
8291 assert(consdata->validglbminact);
8292 }
8293
8294 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8295 {
8297 assert(consdata->validglbmaxact);
8298 }
8299 assert(consdata->validglbminact || consdata->validglbmaxact);
8300
8301 /* sort coefficients non-increasing to be faster in the clique search */
8302 SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8303
8304 /* case a) */
8305 if( finiterhs && finitenegminact && nposbinvars >= 2 )
8306 {
8307 /* compute value that needs to be exceeded */
8308 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8309
8310 j = 1;
8311#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8312 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8313 assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8314#endif
8315 /* check if at least two variables are in a clique */
8316 if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8317 {
8318 ++j;
8319 /* check for extending the clique */
8320 while( j < nposbinvars )
8321 {
8322 if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8323 break;
8324 ++j;
8325 }
8326 assert(j >= 2);
8327
8328 /* add clique with at least two variables */
8329 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8330
8331 if( infeasible )
8332 *cutoff = TRUE;
8333
8334 *nchgbds += nbdchgs;
8335
8336 cliquenonzerosadded += j;
8337 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8338 stopped = TRUE;
8339
8340 /* exchange the last variable in the clique if possible and add all new ones */
8341 if( !stopped && !(*cutoff) && j < nposbinvars )
8342 {
8343 SCIP_VAR** clqvars;
8344 int lastfit = j - 2;
8345 assert(lastfit >= 0);
8346
8347 /* copy all 'main'-clique variables */
8348 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8349
8350 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8351 while( lastfit >= 0 && j < nposbinvars )
8352 {
8353 /* check if two variables are in a clique */
8354 if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8355 {
8356 clqvars[lastfit + 1] = binvars[j];
8357
8358 /* add clique with at least two variables */
8359 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8360
8361 if( infeasible )
8362 {
8363 *cutoff = TRUE;
8364 break;
8365 }
8366
8367 *nchgbds += nbdchgs;
8368
8369 cliquenonzerosadded += (lastfit + 2);
8370 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8371 {
8372 stopped = TRUE;
8373 break;
8374 }
8375
8376 ++j;
8377 }
8378 else
8379 --lastfit;
8380 }
8381
8382 SCIPfreeBufferArray(scip, &clqvars);
8383 }
8384 }
8385 }
8386
8387 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8388 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8389 {
8390 /* check for fixed variables */
8391 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8392
8393 if( !*cutoff )
8394 {
8395 /* tighten variable's bounds */
8396 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8397
8398 if( !*cutoff )
8399 {
8400 /* check for fixed variables */
8401 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8402
8403 if( !*cutoff )
8404 {
8405 /* sort variables by variable type */
8406 SCIP_CALL( consdataSort(scip, consdata) );
8407
8408 /* recompute activities if needed */
8409 if( !consdata->validactivities )
8410 consdataCalcActivities(scip, consdata);
8411 assert(consdata->validactivities);
8412
8413 nvars = consdata->nvars;
8414 vars = consdata->vars;
8415 vals = consdata->vals;
8416 nposbinvars = 0;
8417 nnegbinvars = 0;
8418 allonebinary = 0;
8419
8420 /* update binary variables */
8421 for( i = 0; i < nvars; ++i )
8422 {
8423 if( SCIPvarIsBinary(vars[i]) )
8424 {
8425 assert(!SCIPisZero(scip, vals[i]));
8426
8427 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8428 ++allonebinary;
8429
8430 binvars[nposbinvars + nnegbinvars] = vars[i];
8431 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8432
8433 if( SCIPisPositive(scip, vals[i]) )
8434 ++nposbinvars;
8435 else
8436 ++nnegbinvars;
8437
8438 assert(nposbinvars + nnegbinvars <= nvars);
8439 }
8440 /* stop searching for binary variables, because the constraint data is sorted */
8441 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8442 break;
8443 }
8444 assert(nposbinvars + nnegbinvars <= nvars);
8445 }
8446 }
8447 }
8448
8449 oldnchgbds = *nchgbds;
8450 }
8451
8452 /* case b) */
8453 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8454 {
8455 /* compute value that needs to be deceeded */
8456 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8457
8458 i = nposbinvars + nnegbinvars - 1;
8459 j = i - 1;
8460#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8461 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8462 assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8463#endif
8464 /* check if two variables are in a clique */
8465 if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8466 {
8467 --j;
8468 /* check for extending the clique */
8469 while( j >= nposbinvars )
8470 {
8471 if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8472 break;
8473 --j;
8474 }
8475 jstart = j;
8476
8477 assert(i - j >= 2);
8478 /* add clique with at least two variables */
8479 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8480
8481 if( infeasible )
8482 *cutoff = TRUE;
8483
8484 *nchgbds += nbdchgs;
8485
8486 cliquenonzerosadded += (i - j);
8487 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8488 stopped = TRUE;
8489
8490 /* exchange the last variable in the clique if possible and add all new ones */
8491 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8492 {
8493 SCIP_VAR** clqvars;
8494 int lastfit = jstart + 1;
8495 assert(lastfit < i);
8496
8497 /* copy all 'main'-clique variables */
8498 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8499 ++lastfit;
8500
8501 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8502 while( lastfit <= i && j >= nposbinvars )
8503 {
8504 /* check if two variables are in a clique */
8505 if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8506 {
8507 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8508 clqvars[lastfit - jstart - 2] = binvars[j];
8509
8510 assert(i - lastfit + 2 >= 2);
8511 /* add clique with at least two variables */
8512 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8513
8514 if( infeasible )
8515 {
8516 *cutoff = TRUE;
8517 break;
8518 }
8519
8520 *nchgbds += nbdchgs;
8521
8522 cliquenonzerosadded += (i - lastfit + 2);
8523 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8524 {
8525 stopped = TRUE;
8526 break;
8527 }
8528
8529 --j;
8530 }
8531 else
8532 ++lastfit;
8533 }
8534
8535 SCIPfreeBufferArray(scip, &clqvars);
8536 }
8537 }
8538 }
8539
8540 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8541 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8542 {
8543 /* check for fixed variables */
8544 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8545
8546 if( !*cutoff )
8547 {
8548 /* tighten variable's bounds */
8549 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8550
8551 if( !*cutoff )
8552 {
8553 /* check for fixed variables */
8554 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8555
8556 if( !*cutoff )
8557 {
8558 /* sort variables by variable type */
8559 SCIP_CALL( consdataSort(scip, consdata) );
8560
8561 /* recompute activities if needed */
8562 if( !consdata->validactivities )
8563 consdataCalcActivities(scip, consdata);
8564 assert(consdata->validactivities);
8565
8566 nvars = consdata->nvars;
8567 vars = consdata->vars;
8568 vals = consdata->vals;
8569 nposbinvars = 0;
8570 nnegbinvars = 0;
8571 allonebinary = 0;
8572
8573 /* update binary variables */
8574 for( i = 0; i < nvars; ++i )
8575 {
8576 if( SCIPvarIsBinary(vars[i]) )
8577 {
8578 assert(!SCIPisZero(scip, vals[i]));
8579
8580 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8581 ++allonebinary;
8582
8583 binvars[nposbinvars + nnegbinvars] = vars[i];
8584 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8585
8586 if( SCIPisPositive(scip, vals[i]) )
8587 ++nposbinvars;
8588 else
8589 ++nnegbinvars;
8590
8591 assert(nposbinvars + nnegbinvars <= nvars);
8592 }
8593 /* stop searching for binary variables, because the constraint data is sorted */
8594 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8595 break;
8596 }
8597 assert(nposbinvars + nnegbinvars <= nvars);
8598 }
8599 }
8600 }
8601
8602 oldnchgbds = *nchgbds;
8603 }
8604
8605 /* case c) */
8606 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8607 {
8608 SCIP_Bool* values;
8609
8610 /* initialize clique values array for adding a negated clique */
8611 SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8612 BMSclearMemoryArray(values, nnegbinvars);
8613
8614 /* compute value that needs to be exceeded */
8615 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8616
8617 i = nposbinvars + nnegbinvars - 1;
8618 j = i - 1;
8619
8620#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8621 /* check if the variable should not have already been fixed to one */
8622 assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8623#endif
8624
8625 if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8626 {
8627 --j;
8628 /* check for extending the clique */
8629 while( j >= nposbinvars )
8630 {
8631 if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8632 break;
8633 --j;
8634 }
8635 jstart = j;
8636
8637 assert(i - j >= 2);
8638 /* add negated clique with at least two variables */
8639 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8640
8641 if( infeasible )
8642 *cutoff = TRUE;
8643
8644 *nchgbds += nbdchgs;
8645
8646 cliquenonzerosadded += (i - j);
8647 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8648 stopped = TRUE;
8649
8650 /* exchange the last variable in the clique if possible and add all new ones */
8651 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8652 {
8653 SCIP_VAR** clqvars;
8654 int lastfit = j + 1;
8655 assert(lastfit < i);
8656
8657 /* copy all 'main'-clique variables */
8658 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8659 ++lastfit;
8660
8661 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8662 while( lastfit <= i && j >= nposbinvars )
8663 {
8664 /* check if two variables are in a negated clique */
8665 if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8666 {
8667 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8668 clqvars[lastfit - jstart - 2] = binvars[j];
8669
8670 assert(i - lastfit + 2 >= 2);
8671 /* add clique with at least two variables */
8672 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8673
8674 if( infeasible )
8675 {
8676 *cutoff = TRUE;
8677 break;
8678 }
8679
8680 *nchgbds += nbdchgs;
8681
8682 cliquenonzerosadded += (i - lastfit + 2);
8683 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8684 {
8685 stopped = TRUE;
8686 break;
8687 }
8688
8689 --j;
8690 }
8691 else
8692 ++lastfit;
8693 }
8694
8695 SCIPfreeBufferArray(scip, &clqvars);
8696 }
8697 }
8698
8699 SCIPfreeBufferArray(scip, &values);
8700 }
8701
8702 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8703 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8704 {
8705 /* check for fixed variables */
8706 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8707
8708 if( !*cutoff )
8709 {
8710 /* tighten variable's bounds */
8711 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8712
8713 if( !*cutoff )
8714 {
8715 /* check for fixed variables */
8716 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8717
8718 if( !*cutoff )
8719 {
8720 /* sort variables by variable type */
8721 SCIP_CALL( consdataSort(scip, consdata) );
8722
8723 /* recompute activities if needed */
8724 if( !consdata->validactivities )
8725 consdataCalcActivities(scip, consdata);
8726 assert(consdata->validactivities);
8727
8728 nvars = consdata->nvars;
8729 vars = consdata->vars;
8730 vals = consdata->vals;
8731 nposbinvars = 0;
8732 nnegbinvars = 0;
8733 allonebinary = 0;
8734
8735 /* update binary variables */
8736 for( i = 0; i < nvars; ++i )
8737 {
8738 if( SCIPvarIsBinary(vars[i]) )
8739 {
8740 assert(!SCIPisZero(scip, vals[i]));
8741
8742 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8743 ++allonebinary;
8744
8745 binvars[nposbinvars + nnegbinvars] = vars[i];
8746 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8747
8748 if( SCIPisPositive(scip, vals[i]) )
8749 ++nposbinvars;
8750 else
8751 ++nnegbinvars;
8752
8753 assert(nposbinvars + nnegbinvars <= nvars);
8754 }
8755 /* stop searching for binary variables, because the constraint data is sorted */
8756 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8757 break;
8758 }
8759 assert(nposbinvars + nnegbinvars <= nvars);
8760 }
8761 }
8762 }
8763 }
8764
8765 /* case d) */
8766 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8767 {
8768 SCIP_Bool* values;
8769
8770 /* initialize clique values array for adding a negated clique */
8771 SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8772 BMSclearMemoryArray(values, nposbinvars);
8773
8774 /* compute value that needs to be exceeded */
8775 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8776
8777 j = 1;
8778
8779#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8780 /* check if the variable should not have already been fixed to one */
8781 assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8782#endif
8783
8784 if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8785 {
8786 ++j;
8787 /* check for extending the clique */
8788 while( j < nposbinvars )
8789 {
8790 if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8791 break;
8792 ++j;
8793 }
8794 assert(j >= 2);
8795
8796 /* add negated clique with at least two variables */
8797 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8798
8799 if( infeasible )
8800 *cutoff = TRUE;
8801
8802 *nchgbds += nbdchgs;
8803
8804 cliquenonzerosadded += j;
8805 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8806 stopped = TRUE;
8807
8808 /* exchange the last variable in the clique if possible and add all new ones */
8809 if( !stopped && !(*cutoff) && j < nposbinvars )
8810 {
8811 SCIP_VAR** clqvars;
8812 int lastfit = j - 2;
8813 assert(lastfit >= 0);
8814
8815 /* copy all 'main'-clique variables */
8816 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8817
8818 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8819 while( lastfit >= 0 && j < nposbinvars )
8820 {
8821 /* check if two variables are in a negated clique */
8822 if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8823 {
8824 clqvars[lastfit + 1] = binvars[j];
8825
8826 /* add clique with at least two variables */
8827 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8828
8829 if( infeasible )
8830 {
8831 *cutoff = TRUE;
8832 break;
8833 }
8834
8835 *nchgbds += nbdchgs;
8836
8837 cliquenonzerosadded += lastfit + 2;
8838 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8839 break;
8840
8841 ++j;
8842 }
8843 else
8844 --lastfit;
8845 }
8846
8847 SCIPfreeBufferArray(scip, &clqvars);
8848 }
8849 }
8850
8851 SCIPfreeBufferArray(scip, &values);
8852 }
8853 }
8854
8855 SCIPfreeBufferArray(scip, &binvarvals);
8856 SCIPfreeBufferArray(scip, &binvars);
8857
8858 if( *cutoff )
8859 return SCIP_OKAY;
8860 }
8861
8862 /* 2. we only check if the constraint is a set packing / partitioning constraint */
8863
8864 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8865 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8866 */
8867 nposcoefs = 0;
8868 nnegcoefs = 0;
8869 for( i = 0; i < nvars; ++i )
8870 {
8871 if( !SCIPvarIsBinary(vars[i]) )
8872 return SCIP_OKAY;
8873 else if( SCIPisEQ(scip, vals[i], +1.0) )
8874 nposcoefs++;
8875 else if( SCIPisEQ(scip, vals[i], -1.0) )
8876 nnegcoefs++;
8877 else
8878 return SCIP_OKAY;
8879 }
8880
8881 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8882 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8883
8884 if( lhsclique || rhsclique )
8885 {
8886 SCIP_Bool* values;
8887 int nbdchgs;
8888
8889 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8890 SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8891 SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8892
8893 for( i = 0; i < nvars; ++i )
8894 values[i] = (rhsclique == (vals[i] > 0.0));
8895
8896 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8897
8898 if( infeasible )
8899 *cutoff = TRUE;
8900
8901 *nchgbds += nbdchgs;
8902 SCIPfreeBufferArray(scip, &values);
8903 }
8904
8905 return SCIP_OKAY;
8906}
8907
8908/** tightens left and right hand side of constraint due to integrality */
8909static
8911 SCIP* scip, /**< SCIP data structure */
8912 SCIP_CONS* cons, /**< linear constraint */
8913 int* nchgsides, /**< pointer to count number of side changes */
8914 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8915 )
8916{
8917 SCIP_CONSDATA* consdata;
8918 SCIP_Real newlhs;
8919 SCIP_Real newrhs;
8920 SCIP_Bool chglhs;
8921 SCIP_Bool chgrhs;
8922 SCIP_Bool integral;
8923 int i;
8924
8925 assert(scip != NULL);
8926 assert(cons != NULL);
8927 assert(nchgsides != NULL);
8928 assert(infeasible != NULL);
8929
8930 consdata = SCIPconsGetData(cons);
8931 assert(consdata != NULL);
8932
8933 *infeasible = FALSE;
8934
8935 chglhs = FALSE;
8936 chgrhs = FALSE;
8937 newlhs = -SCIPinfinity(scip);
8938 newrhs = SCIPinfinity(scip);
8939
8940 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8941 {
8942 integral = TRUE;
8943 for( i = 0; i < consdata->nvars && integral; ++i )
8944 {
8945 integral = SCIPisIntegral(scip, consdata->vals[i])
8946 && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
8947 }
8948 if( integral )
8949 {
8950 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8951 {
8952 newlhs = SCIPfeasCeil(scip, consdata->lhs);
8953 chglhs = TRUE;
8954 }
8955 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8956 {
8957 newrhs = SCIPfeasFloor(scip, consdata->rhs);
8958 chgrhs = TRUE;
8959 }
8960
8961 /* check whether rounding would lead to an unsatisfiable constraint */
8962 if( SCIPisGT(scip, newlhs, newrhs) )
8963 {
8964 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
8965 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
8966
8967 *infeasible = TRUE;
8968 return SCIP_OKAY;
8969 }
8970
8971 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8972 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8973
8974 if( chglhs )
8975 {
8976 assert(!SCIPisInfinity(scip, -newlhs));
8977
8978 SCIP_CALL( chgLhs(scip, cons, newlhs) );
8979 if( !consdata->upgraded )
8980 (*nchgsides)++;
8981 }
8982 if( chgrhs )
8983 {
8984 assert(!SCIPisInfinity(scip, newrhs));
8985
8986 SCIP_CALL( chgRhs(scip, cons, newrhs) );
8987 if( !consdata->upgraded )
8988 (*nchgsides)++;
8989 }
8990 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8991 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8992 }
8993 }
8994
8995 return SCIP_OKAY;
8996}
8997
8998/** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
8999 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
9000 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
9001 * (i) ai >= 0:
9002 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
9003 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
9004 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9005 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9006 * - change coefficients:
9007 * ai' := max(lhs - minact, maxact - rhs, 0)
9008 * lhs' := lhs - (ai - ai')*li
9009 * rhs' := rhs - (ai - ai')*ui
9010 * (ii) ai < 0:
9011 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9012 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9013 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9014 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9015 * - change coefficients:
9016 * ai' := min(rhs - maxact, minact - lhs, 0)
9017 * lhs' := lhs - (ai - ai')*ui
9018 * rhs' := rhs - (ai - ai')*li
9019 *
9020 * We further try to remove variables from the constraint;
9021 * Variables which fulfill conditions (**) or (***) are called relevant variables.
9022 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9023 * variables are set to their "worst" bound. If all variables which are not relevant cannot make the lhs/rhs
9024 * redundant, even if they are set to their "best" bound, they can be removed from the constraint. E.g., for binary
9025 * 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
9026 * inequality, whereas the x_i do not contribute to feasibility and can be removed.
9027 *
9028 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9029 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9030 */
9031static
9033 SCIP* scip, /**< SCIP data structure */
9034 SCIP_CONS* cons, /**< linear constraint */
9035 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9036 int* nchgsides /**< pointer to count number of side changes */
9037 )
9038{
9039 SCIP_CONSDATA* consdata;
9040 SCIP_VAR* var;
9041 SCIP_Bool* isvarrelevant;
9042 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9043 * activity, ignoring the coefficients contributing with infinite value */
9044 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9045 * activity, ignoring the coefficients contributing with infinite value */
9046 SCIP_Bool isminacttight; /* are all contributions to the minactivity non-huge or non-contradicting? */
9047 SCIP_Bool ismaxacttight; /* are all contributions to the maxactivity non-huge or non-contradicting? */
9048 SCIP_Bool isminsettoinfinity;
9049 SCIP_Bool ismaxsettoinfinity;
9050 SCIP_Real minleftactivity; /* minimal activity without relevant variables */
9051 SCIP_Real maxleftactivity; /* maximal activity without relevant variables */
9052 SCIP_Real aggrlhs; /* lhs without minimal activity of relevant variables */
9053 SCIP_Real aggrrhs; /* rhs without maximal activity of relevant variables */
9054 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9055 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9056 SCIP_Real val;
9057 SCIP_Real newval;
9058 SCIP_Real newlhs;
9059 SCIP_Real newrhs;
9060 SCIP_Real lb;
9061 SCIP_Real ub;
9062 int i;
9063
9064 assert(scip != NULL);
9065 assert(cons != NULL);
9066 assert(nchgcoefs != NULL);
9067 assert(nchgsides != NULL);
9068
9069 consdata = SCIPconsGetData(cons);
9070 assert(consdata != NULL);
9071
9072 /* allocate relevance flags */
9073 SCIP_CALL( SCIPallocBufferArray(scip, &isvarrelevant, consdata->nvars) );
9074
9075 /* @todo Is this still needed with automatic recomputation of activities? */
9076 /* if the maximal coefficient is too large, recompute the activities */
9077 if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9078 || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9079 {
9082 }
9083
9084 /* get the minimal and maximal activity of the constraint */
9085 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9086 &isminsettoinfinity, &ismaxsettoinfinity);
9087 assert(( isminsettoinfinity && !SCIPisInfinity(scip, -consdata->lhs) )
9088 || SCIPisLT(scip, minactivity, consdata->lhs)
9089 || ( ismaxsettoinfinity && !SCIPisInfinity(scip, consdata->rhs) )
9090 || SCIPisGT(scip, maxactivity, consdata->rhs));
9091
9092 minleftactivity = 0.0;
9093 maxleftactivity = 0.0;
9094
9095 /* try to tighten each coefficient */
9096 i = 0;
9097 while( i < consdata->nvars )
9098 {
9099 /* get coefficient and variable's bounds */
9100 var = consdata->vars[i];
9101 val = consdata->vals[i];
9102 assert(!SCIPisZero(scip, val));
9103 lb = SCIPvarGetLbLocal(var);
9104 ub = SCIPvarGetUbLocal(var);
9105
9106 /* check sign of coefficient */
9107 if( val >= 0.0 )
9108 {
9109 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9110 isvarrelevant[i] = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS
9111 && SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs);
9112
9113 if( isvarrelevant[i] )
9114 {
9115 /* change coefficients:
9116 * ai' := max(lhs - minact, maxact - rhs)
9117 * lhs' := lhs - (ai - ai')*li
9118 * rhs' := rhs - (ai - ai')*ui
9119 */
9120
9121 lval = consdata->lhs - minactivity;
9122 rval = maxactivity - consdata->rhs;
9123
9124 /* Try to avoid cancellation, if there are only two variables */
9125 if( consdata->nvars == 2 )
9126 {
9127 SCIP_Real otherval;
9128 otherval = consdata->vals[1-i];
9129
9130 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9131 {
9132 lval = consdata->lhs - val*lb;
9133 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9134 }
9135
9136 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9137 {
9138 rval = val*ub - consdata->rhs;
9139 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9140 }
9141 }
9142
9143 newval = MAX3(lval, rval, 0.0);
9144 assert(SCIPisSumRelLE(scip, newval, val));
9145
9146 /* Try to avoid cancellation in computation of lhs/rhs */
9147 newlhs = consdata->lhs - val * lb;
9148 newlhs += newval * lb;
9149 newrhs = consdata->rhs - val * ub;
9150 newrhs += newval * ub;
9151
9152 if( !SCIPisSumRelEQ(scip, newval, val) )
9153 {
9154 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9155 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9156 maxactivity, consdata->lhs, consdata->rhs);
9157
9158 /* update the coefficient and the activity bounds */
9159 if( SCIPisZero(scip, newval) )
9160 {
9161 SCIP_CALL( delCoefPos(scip, cons, i) );
9162 --i;
9163 }
9164 else
9165 {
9166 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9167 }
9168 ++(*nchgcoefs);
9169
9170 /* get the new minimal and maximal activity of the constraint */
9171 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9172 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9173
9174 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9175 {
9176 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9177 consdata->lhs, newlhs);
9178
9179 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9180 (*nchgsides)++;
9181 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9182 }
9183
9184 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9185 {
9186 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9187 consdata->rhs, newrhs);
9188
9189 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9190 (*nchgsides)++;
9191 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9192 }
9193 }
9194 }
9195 else
9196 {
9197 if( !SCIPisInfinity(scip, -minleftactivity) )
9198 {
9199 assert(!SCIPisInfinity(scip, val));
9200 assert(!SCIPisInfinity(scip, lb));
9201 if( SCIPisInfinity(scip, -lb) )
9202 minleftactivity = -SCIPinfinity(scip);
9203 else
9204 minleftactivity += val * lb;
9205 }
9206
9207 if( !SCIPisInfinity(scip, maxleftactivity) )
9208 {
9209 assert(!SCIPisInfinity(scip, val));
9210 assert(!SCIPisInfinity(scip, -ub));
9211 if( SCIPisInfinity(scip,ub) )
9212 maxleftactivity = SCIPinfinity(scip);
9213 else
9214 maxleftactivity += val * ub;
9215 }
9216 }
9217 }
9218 else
9219 {
9220 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9221 isvarrelevant[i] = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS
9222 && SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs);
9223
9224 if( isvarrelevant[i] )
9225 {
9226 /* change coefficients:
9227 * ai' := min(rhs - maxact, minact - lhs)
9228 * lhs' := lhs - (ai - ai')*ui
9229 * rhs' := rhs - (ai - ai')*li
9230 */
9231
9232 lval = minactivity - consdata->lhs;
9233 rval = consdata->rhs - maxactivity;
9234
9235 /* Try to avoid cancellation, if there are only two variables */
9236 if( consdata->nvars == 2 )
9237 {
9238 SCIP_Real otherval;
9239 otherval = consdata->vals[1-i];
9240
9241 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9242 {
9243 lval = val*ub - consdata->lhs;
9244 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9245 }
9246
9247 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9248 {
9249 rval = consdata->rhs - val*lb;
9250 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9251 }
9252 }
9253
9254 newval = MIN3(lval, rval, 0.0);
9255 assert(SCIPisSumRelGE(scip, newval, val));
9256
9257 /* Try to avoid cancellation in computation of lhs/rhs */
9258 newlhs = consdata->lhs - val * ub;
9259 newlhs += newval * ub;
9260 newrhs = consdata->rhs - val * lb;
9261 newrhs += newval * lb;
9262
9263 if( !SCIPisSumRelEQ(scip, newval, val) )
9264 {
9265 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9266 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9267 maxactivity, consdata->lhs, consdata->rhs);
9268
9269 /* update the coefficient and the activity bounds */
9270 if( SCIPisZero(scip, newval) )
9271 {
9272 SCIP_CALL( delCoefPos(scip, cons, i) );
9273 --i;
9274 }
9275 else
9276 {
9277 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9278 }
9279 ++(*nchgcoefs);
9280
9281 /* get the new minimal and maximal activity of the constraint */
9282 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9283 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9284
9285 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9286 {
9287 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9288 consdata->lhs, newlhs);
9289
9290 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9291 (*nchgsides)++;
9292 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9293 }
9294
9295 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9296 {
9297 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9298 consdata->rhs, newrhs);
9299
9300 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9301 (*nchgsides)++;
9302 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9303 }
9304 }
9305 }
9306 else
9307 {
9308 if( !SCIPisInfinity(scip, -minleftactivity) )
9309 {
9310 assert(!SCIPisInfinity(scip, -val));
9311 assert(!SCIPisInfinity(scip, -ub));
9312 if( SCIPisInfinity(scip, ub) )
9313 minleftactivity = -SCIPinfinity(scip);
9314 else
9315 minleftactivity += val * ub;
9316 }
9317
9318 if( !SCIPisInfinity(scip, maxleftactivity) )
9319 {
9320 assert(!SCIPisInfinity(scip, -val));
9321 assert(!SCIPisInfinity(scip, lb));
9322 if( SCIPisInfinity(scip, -lb) )
9323 maxleftactivity = SCIPinfinity(scip);
9324 else
9325 maxleftactivity += val * lb;
9326 }
9327 }
9328 }
9329
9330 ++i;
9331 }
9332
9333 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9334 minleftactivity, consdata->rhs);
9335 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9336 maxleftactivity, consdata->lhs);
9337
9338 /* minleft == \infty ==> minactivity == \infty */
9339 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9340 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9341
9342 /* if the lhs is finite, we will check in the following whether the not relevant variables can make lhs feasible;
9343 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9344 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9345 * (<= the exact minactivity), and we might falsely remove coefficients in the following
9346 */
9347 assert(!SCIPisInfinity(scip, minactivity));
9348 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
9349 goto TERMINATE;
9350
9351 /* if the rhs is finite, we will check in the following whether the not relevant variables can make rhs feasible;
9352 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9353 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9354 * (>= the exact maxactivity), and we might falsely remove coefficients in the following
9355 */
9356 assert(!SCIPisInfinity(scip, -maxactivity));
9357 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
9358 goto TERMINATE;
9359
9360 /* correct lhs and rhs by min/max activity of relevant variables
9361 * relevant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9362 */
9363 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9364 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9365
9366 /* check if the constraint contains variables whose coefficient can be removed. The reasoning is the following:
9367 * Each relevant variable can make the lhs/rhs feasible with a deviation of only one in the bound. If _all_ not
9368 * relevant variables together cannot make lhs/rhs redundant, they can be removed from the constraint. aggrrhs may
9369 * contain some near-infinity value, but only if rhs is infinity.
9370 */
9371 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9372 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9373 {
9374 SCIP_Real minleftactivitypart;
9375 SCIP_Real maxleftactivitypart;
9376
9377 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9378
9379 /* remove redundant variables from constraint */
9380 i = 0;
9381 while( i < consdata->nvars )
9382 {
9383 /* consider redundant variable */
9384 if( !isvarrelevant[i] )
9385 {
9386 /* get coefficient and variable's bounds */
9387 var = consdata->vars[i];
9388 val = consdata->vals[i];
9389 assert(!SCIPisZero(scip, val));
9390 lb = SCIPvarGetLbLocal(var);
9391 ub = SCIPvarGetUbLocal(var);
9392
9393 SCIPdebugMsg(scip, "val = %g\tlhs = %g\trhs = %g\n", val, consdata->lhs, consdata->rhs);
9394 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> from constraint since it is redundant\n",
9395 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
9396
9397 /* check sign of coefficient */
9398 if( val >= 0.0 )
9399 {
9400 minleftactivitypart = val * lb;
9401 maxleftactivitypart = val * ub;
9402 }
9403 else
9404 {
9405 minleftactivitypart = val * ub;
9406 maxleftactivitypart = val * lb;
9407 }
9408
9409 /* remove redundant variable */
9410 isvarrelevant[i] = isvarrelevant[consdata->nvars - 1];
9411 SCIP_CALL( delCoefPos(scip, cons, i) );
9412 --i;
9413
9414 /* adjust lhs and right hand side */
9415 newlhs = consdata->lhs - minleftactivitypart;
9416 newrhs = consdata->rhs - maxleftactivitypart;
9417
9418 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9419 {
9420 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9421 consdata->lhs, newlhs);
9422
9423 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9424 ++(*nchgsides);
9425 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9426 }
9427
9428 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9429 {
9430 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9431 consdata->rhs, newrhs);
9432
9433 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9434 ++(*nchgsides);
9435 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9436 }
9437 }
9438
9439 ++i;
9440 }
9441 }
9442
9443TERMINATE:
9444 /* free relevance flags */
9445 SCIPfreeBufferArray(scip, &isvarrelevant);
9446
9447 return SCIP_OKAY;
9448}
9449
9450/** processes equality with only one variable by fixing the variable and deleting the constraint */
9451static
9453 SCIP* scip, /**< SCIP data structure */
9454 SCIP_CONS* cons, /**< linear constraint */
9455 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9456 int* nfixedvars, /**< pointer to count number of fixed variables */
9457 int* ndelconss /**< pointer to count number of deleted constraints */
9458 )
9459{
9460 SCIP_CONSDATA* consdata;
9461 SCIP_VAR* var;
9462 SCIP_Real val;
9463 SCIP_Real fixval;
9464 SCIP_Bool infeasible;
9465 SCIP_Bool fixed;
9466
9467 assert(scip != NULL);
9468 assert(cons != NULL);
9469 assert(cutoff != NULL);
9470 assert(nfixedvars != NULL);
9471 assert(ndelconss != NULL);
9472
9473 consdata = SCIPconsGetData(cons);
9474 assert(consdata != NULL);
9475 assert(consdata->nvars == 1);
9476 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9477
9478 /* calculate the value to fix the variable to */
9479 var = consdata->vars[0];
9480 val = consdata->vals[0];
9481 assert(!SCIPisZero(scip, val));
9482 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9483 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9484 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9485 SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9486
9487 /* fix variable */
9488 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9489 if( infeasible )
9490 {
9491 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9492 *cutoff = TRUE;
9493 return SCIP_OKAY;
9494 }
9495 if( fixed )
9496 (*nfixedvars)++;
9497
9498 /* disable constraint */
9499 SCIP_CALL( SCIPdelCons(scip, cons) );
9500 if( !consdata->upgraded )
9501 (*ndelconss)++;
9502
9503 return SCIP_OKAY;
9504}
9505
9506/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9507static
9509 SCIP* scip, /**< SCIP data structure */
9510 SCIP_CONS* cons, /**< linear constraint */
9511 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9512 int* naggrvars, /**< pointer to count number of aggregated variables */
9513 int* ndelconss /**< pointer to count number of deleted constraints */
9514 )
9515{
9516 SCIP_CONSDATA* consdata;
9517 SCIP_Bool infeasible;
9518 SCIP_Bool redundant;
9519 SCIP_Bool aggregated;
9520
9521 assert(scip != NULL);
9522 assert(cons != NULL);
9523 assert(cutoff != NULL);
9524 assert(naggrvars != NULL);
9525 assert(ndelconss != NULL);
9526
9527 consdata = SCIPconsGetData(cons);
9528 assert(consdata != NULL);
9529 assert(consdata->nvars == 2);
9530 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9531
9532 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9533 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9534 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9535
9536 /* aggregate the equality */
9537 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9538 consdata->rhs, &infeasible, &redundant, &aggregated) );
9539
9540 /* check for infeasibility of aggregation */
9541 if( infeasible )
9542 {
9543 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9544 *cutoff = TRUE;
9545 return SCIP_OKAY;
9546 }
9547
9548 /* count the aggregation */
9549 if( aggregated )
9550 (*naggrvars)++;
9551
9552 /* delete the constraint, if it is redundant */
9553 if( redundant )
9554 {
9555 SCIP_CALL( SCIPdelCons(scip, cons) );
9556
9557 if( !consdata->upgraded )
9558 (*ndelconss)++;
9559 }
9560
9561 return SCIP_OKAY;
9562}
9563
9564/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9565static
9567 SCIP* scip, /**< SCIP data structure */
9568 SCIP_CONSDATA* consdata, /**< linear constraint data */
9569 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9570 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9571 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9572 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9573 )
9574{
9575 SCIP_Real slackvarlb;
9576 SCIP_Real slackvarub;
9577
9578 assert(scip != NULL);
9579 assert(consdata != NULL);
9580 assert(newlhs != NULL);
9581 assert(newrhs != NULL);
9582 assert(!SCIPisInfinity(scip, -consdata->lhs));
9583 assert(!SCIPisInfinity(scip, consdata->rhs));
9584
9585 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9586 slackvarub = SCIPvarGetUbGlobal(slackvar);
9587 if( slackcoef > 0.0 )
9588 {
9589 if( SCIPisInfinity(scip, -slackvarlb) )
9590 *newrhs = SCIPinfinity(scip);
9591 else
9592 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9593 if( SCIPisInfinity(scip, slackvarub) )
9594 *newlhs = -SCIPinfinity(scip);
9595 else
9596 *newlhs = consdata->lhs - slackcoef * slackvarub;
9597 }
9598 else
9599 {
9600 if( SCIPisInfinity(scip, -slackvarlb) )
9601 *newlhs = -SCIPinfinity(scip);
9602 else
9603 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9604 if( SCIPisInfinity(scip, slackvarub) )
9605 *newrhs = SCIPinfinity(scip);
9606 else
9607 *newrhs = consdata->lhs - slackcoef * slackvarub;
9608 }
9609 assert(SCIPisLE(scip, *newlhs, *newrhs));
9610}
9611
9612/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9613 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9614 * is implicitly integral by this constraint
9615 *
9616 * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9617 * can help.
9618 */
9619static
9621 SCIP* scip, /**< SCIP data structure */
9622 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9623 SCIP_CONS* cons, /**< linear constraint */
9624 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9625 int* naggrvars, /**< pointer to count number of aggregated variables */
9626 int* ndelconss, /**< pointer to count number of deleted constraints */
9627 int* nchgvartypes /**< pointer to count number of changed variable types */
9628 )
9629{
9630 SCIP_CONSDATA* consdata;
9631 SCIP_VAR** vars;
9632 SCIP_Real* vals;
9633 SCIP_VARTYPE bestslacktype;
9634 SCIP_VARTYPE slacktype;
9635 SCIP_Real lhs;
9636 SCIP_Real rhs;
9637 SCIP_Real bestslackdomrng;
9638 SCIP_Real minabsval;
9639 SCIP_Real maxabsval;
9640 SCIP_Bool bestremovescons;
9641 SCIP_Bool coefszeroone;
9642 SCIP_Bool coefsintegral;
9643 SCIP_Bool varsintegral;
9644 SCIP_Bool infeasible;
9645 SCIP_Bool samevar;
9646 int supinf; /* counter for infinite contributions to the supremum of a possible
9647 * multi-aggregation
9648 */
9649 int infinf; /* counter for infinite contributions to the infimum of a possible
9650 * multi-aggregation
9651 */
9652 int maxnlocksstay;
9653 int maxnlocksremove;
9654 int bestslackpos;
9655 int bestnlocks;
9656 int ncontvars;
9657 int contvarpos;
9658 int nintvars;
9659 int nimplvars;
9660 int intvarpos;
9661 int v;
9662
9663 assert(scip != NULL);
9664 assert(cons != NULL);
9665 assert(cutoff != NULL);
9666 assert(naggrvars != NULL);
9667
9668 consdata = SCIPconsGetData(cons);
9669 assert(consdata != NULL);
9670 assert(consdata->nvars > 2);
9671 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9672
9673 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9674
9675 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9676 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9677 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9678 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9679 */
9680 lhs = consdata->lhs;
9681 rhs = consdata->rhs;
9682 maxnlocksstay = 0;
9683 if( consdata->nvars == 3 )
9684 {
9685 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9686 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9687 */
9688 maxnlocksremove = 3;
9689 }
9690 else if( consdata->nvars == 4 )
9691 {
9692 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9693 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9694 */
9695 maxnlocksremove = 2;
9696 }
9697 else
9698 {
9699 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9700 maxnlocksremove = 1;
9701 }
9702
9703 /* the locks on this constraint can be ignored */
9704 if( SCIPconsIsChecked(cons) )
9705 {
9706 if( !SCIPisInfinity(scip, -lhs) )
9707 {
9708 maxnlocksstay++;
9709 maxnlocksremove++;
9710 }
9711 if( !SCIPisInfinity(scip, rhs) )
9712 {
9713 maxnlocksstay++;
9714 maxnlocksremove++;
9715 }
9716 }
9717
9718 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9719 vars = consdata->vars;
9720 vals = consdata->vals;
9721 bestslackpos = -1;
9722 bestslacktype = SCIP_VARTYPE_BINARY;
9723 bestnlocks = INT_MAX;
9724 bestremovescons = FALSE;
9725 bestslackdomrng = 0.0;
9726 coefszeroone = TRUE;
9727 coefsintegral = TRUE;
9728 varsintegral = TRUE;
9729 ncontvars = 0;
9730 contvarpos = -1;
9731 nintvars = 0;
9732 nimplvars = 0;
9733 intvarpos = -1;
9734 minabsval = SCIPinfinity(scip);
9735 maxabsval = -1.0;
9736 for( v = 0; v < consdata->nvars; ++v )
9737 {
9738 SCIP_VAR* var;
9739 SCIP_Real val;
9740 SCIP_Real absval;
9741 SCIP_Real varlb;
9742 SCIP_Real varub;
9743 SCIP_Bool iscont;
9744 int nlocks;
9745
9746 assert(vars != NULL);
9747 assert(vals != NULL);
9748
9749 var = vars[v];
9750 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9752 varlb = SCIPvarGetLbGlobal(var);
9753 varub = SCIPvarGetUbGlobal(var);
9754
9755 val = vals[v];
9756 absval = REALABS(val);
9757 assert(SCIPisPositive(scip, absval));
9758
9759 /* calculate minimal and maximal absolute value */
9760 if( absval < minabsval )
9761 minabsval = absval;
9762 if( absval > maxabsval )
9763 maxabsval = absval;
9764
9765 /*TODO: why exit here when implied integrality can still be derived?!*/
9766 /* do not try to multi aggregate, when numerical bad */
9767 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9768 return SCIP_OKAY;
9769
9770 slacktype = SCIPvarGetType(var);
9771 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9772 coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9773 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9774 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9775
9776 /* update candidates for continuous -> implint and integer -> implint conversion */
9777 if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9778 {
9779 ncontvars++;
9780 contvarpos = v;
9781 }
9782 else if( slacktype == SCIP_VARTYPE_IMPLINT )
9783 {
9784 ++nimplvars;
9785 }
9786 else if( slacktype == SCIP_VARTYPE_INTEGER )
9787 {
9788 nintvars++;
9789 intvarpos = v;
9790 }
9791
9792 /* check, if variable is already fixed or aggregated */
9793 if( !SCIPvarIsActive(var) )
9794 continue;
9795
9796 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9798
9799 if( nlocks > maxnlocksremove )
9800 continue;
9801
9802 /* check, if variable can be used as a slack variable */
9803 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9804 !SCIPdoNotMultaggrVar(scip, var) )
9805 {
9806 SCIP_Bool better;
9807 SCIP_Bool equal;
9808 SCIP_Real slackdomrng;
9809
9810 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9811 slackdomrng = SCIPinfinity(scip);
9812 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9813 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9814 return SCIP_OKAY;
9815 else
9816 {
9817 slackdomrng = (varub - varlb)*absval;
9818 assert(!SCIPisInfinity(scip, slackdomrng));
9819 }
9820 equal = FALSE;
9821 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9822 if( !better && slacktype == bestslacktype )
9823 {
9824 better = (nlocks < bestnlocks);
9825 if( nlocks == bestnlocks && !bestremovescons )
9826 {
9827 better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9828 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9829 }
9830 }
9831
9832 if( better || equal )
9833 {
9834 SCIP_Real minresactivity;
9835 SCIP_Real maxresactivity;
9836 SCIP_Real newlhs;
9837 SCIP_Real newrhs;
9838 SCIP_Bool removescons;
9839 SCIP_Bool ismintight;
9840 SCIP_Bool ismaxtight;
9841 SCIP_Bool isminsettoinfinity;
9842 SCIP_Bool ismaxsettoinfinity;
9843
9844 /* check if the constraint becomes redundant after multi-aggregation */
9845 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9846 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
9847
9848 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9849 * activity
9850 */
9851 if( !ismintight || !ismaxtight )
9852 continue;
9853
9854 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9855 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9856
9857 /* check resactivities for reliability */
9858 if( removescons )
9859 {
9860 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9861 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9862
9863 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9864 && SCIPisFeasLE(scip, newlhs, minresactivity))
9865 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9866
9867 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9868 }
9869
9870 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9871 if( conshdlrdata->multaggrremove && !removescons )
9872 continue;
9873
9874 /* prefer variables that make the constraints redundant */
9875 if( bestremovescons && !removescons )
9876 continue;
9877
9878 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9879 * other constraints
9880 */
9881 if( !removescons && nlocks > maxnlocksstay )
9882 continue;
9883
9884 better = better || (!bestremovescons && removescons);
9885 if( better )
9886 {
9887 bestslackpos = v;
9888 bestslacktype = slacktype;
9889 bestnlocks = nlocks;
9890 bestslackdomrng = slackdomrng;
9891 bestremovescons = removescons;
9892 }
9893 }
9894 }
9895 }
9896
9897 /* if all coefficients and variables are integral, the right hand side must also be integral */
9898 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9899 {
9900 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9902 *cutoff = TRUE;
9903 return SCIP_OKAY;
9904 }
9905
9906 supinf = 0;
9907 infinf = 0;
9908 samevar = FALSE;
9909
9910 /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9911 for( v = 0; v < consdata->nvars; ++v )
9912 {
9913 if( v != bestslackpos )
9914 {
9915 if( SCIPisPositive(scip, consdata->vals[v]) )
9916 {
9917 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9918 {
9919 ++supinf;
9920 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9921 {
9922 ++infinf;
9923 samevar = TRUE;
9924 }
9925 }
9926 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9927 ++infinf;
9928 }
9929 else if( SCIPisNegative(scip, consdata->vals[v]) )
9930 {
9931 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9932 {
9933 ++supinf;
9934 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9935 {
9936 ++infinf;
9937 samevar = TRUE;
9938 }
9939 }
9940 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9941 ++infinf;
9942 }
9943 }
9944 }
9945 assert(!samevar || (supinf > 0 && infinf > 0));
9946
9947 /*TODO: implint detection again terminates early here*/
9948 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9949 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9950 if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9951 {
9952 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9953 return SCIP_OKAY;
9954 }
9955
9956 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9957 * we cannot aggregate the variable, because the integrality condition would get lost
9958 * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9959 * loose the integrality condition for this variable.
9960 */
9961 if( bestslackpos >= 0
9962 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9963 || (coefsintegral && varsintegral && nimplvars == 0)) )
9964 {
9965 SCIP_VAR* slackvar;
9967 SCIP_Real slackcoef;
9968 SCIP_Real aggrconst;
9969 SCIP_Real newlhs;
9970 SCIP_Real newrhs;
9971 SCIP_Bool aggregated;
9972
9973 /* we found a slack variable that only occurs in at most one other constraint:
9974 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9975 */
9976 assert(bestslackpos < consdata->nvars);
9977
9978 /* do not multi aggregate binary variables */
9979 if( SCIPvarIsBinary(vars[bestslackpos]) )
9980 return SCIP_OKAY;
9981
9982 /* convert equality into inequality by deleting the slack variable:
9983 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9984 */
9985 slackvar = vars[bestslackpos];
9986 slackcoef = vals[bestslackpos];
9987 assert(!SCIPisZero(scip, slackcoef));
9988 aggrconst = consdata->rhs/slackcoef;
9989
9990 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9991 assert(SCIPisLE(scip, newlhs, newrhs));
9992 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9993 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9994 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9995
9996 /* allocate temporary memory */
9997 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
9998
9999 /* set up the multi-aggregation */
10000 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
10001 for( v = 0; v < consdata->nvars; ++v )
10002 {
10003 scalars[v] = -consdata->vals[v]/slackcoef;
10004 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
10005 }
10006 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
10007 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
10008 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
10009
10010 /* perform the multi-aggregation */
10011 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10012 &infeasible, &aggregated) );
10013 assert(aggregated);
10014
10015 /* free temporary memory */
10017
10018 /* check for infeasible aggregation */
10019 if( infeasible )
10020 {
10021 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10022 *cutoff = TRUE;
10023 return SCIP_OKAY;
10024 }
10025
10026 (*naggrvars)++;
10027
10028 /* delete the constraint if it became redundant */
10029 if( bestremovescons )
10030 {
10031 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10032 SCIP_CALL( SCIPdelCons(scip, cons) );
10033
10034 if( !consdata->upgraded )
10035 (*ndelconss)++;
10036 }
10037 }
10038 else if( ncontvars == 1 )
10039 {
10040 SCIP_VAR* var;
10041
10042 assert(0 <= contvarpos && contvarpos < consdata->nvars);
10043 var = vars[contvarpos];
10045
10046 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10047 {
10048 /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10049 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10050 {
10051 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10052 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10053 SCIPconsGetName(cons), SCIPvarGetName(var));
10054 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10055 (*nchgvartypes)++;
10056 if( infeasible )
10057 {
10058 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10059 *cutoff = TRUE;
10060
10061 return SCIP_OKAY;
10062 }
10063 }
10064 /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10065 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10066 else if( !SCIPdoNotAggr(scip) )
10067 {
10068 SCIP_VAR* newvar;
10069 SCIP_Real absval;
10070 char newvarname[SCIP_MAXSTRLEN];
10071 SCIP_Bool redundant;
10072 SCIP_Bool aggregated;
10073
10074 absval = REALABS(vals[contvarpos]);
10075
10076 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10077
10078 /* create new implicit variable for aggregation */
10079 SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10081
10082 /* add new variable to problem */
10083 SCIP_CALL( SCIPaddVar(scip, newvar) );
10084
10085#ifdef WITH_DEBUG_SOLUTION
10086 if( SCIPdebugIsMainscip(scip) )
10087 {
10088 SCIP_Real varval;
10089 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10090 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10091 }
10092#endif
10093
10094 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10095 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10096 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10097
10098 /* aggregate continuous and implicit variable */
10099 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10100
10101 if( infeasible )
10102 {
10103 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10104 SCIPvarGetName(var), SCIPvarGetName(newvar));
10105 *cutoff = TRUE;
10106
10107 /* release implicit variable */
10108 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10109
10110 return SCIP_OKAY;
10111 }
10112
10113 /* release implicit variable */
10114 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10115
10116 if( aggregated )
10117 (*naggrvars)++;
10118 else
10119 return SCIP_OKAY;
10120 }
10121
10122 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10123 * again
10124 */
10125 consdata->boundstightened = 0;
10126 consdata->rangedrowpropagated = 0;
10127 consdata->presolved = FALSE;
10128 }
10129 }
10130 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10131 {
10132 SCIP_VAR* var;
10133
10134 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10135 * -> we don't convert integers into implints if the row is a 0/1-row
10136 */
10137 assert(varsintegral);
10138 assert(0 <= intvarpos && intvarpos < consdata->nvars);
10139 var = vars[intvarpos];
10140 assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10141
10142 if( coefsintegral
10143 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10144 && SCIPisFeasIntegral(scip, consdata->rhs) )
10145 {
10146 /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10147 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10148 SCIPconsGetName(cons), SCIPvarGetName(var));
10149 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10150 (*nchgvartypes)++;
10151 if( infeasible )
10152 {
10153 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10154 *cutoff = TRUE;
10155
10156 return SCIP_OKAY;
10157 }
10158 }
10159 }
10160
10161 return SCIP_OKAY;
10162}
10163
10164/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10165static
10167 SCIP* scip, /**< SCIP data structure */
10168 SCIP_CONSDATA* consdata, /**< linear constraint data */
10169 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10170 * objective function */
10171 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10172 * this constraint */
10173 )
10174{
10175 SCIP_VAR** vars;
10176 SCIP_VAR* var;
10177 SCIP_Real objval;
10178 SCIP_Bool negated;
10179 int nvars;
10180 int v;
10181
10182 vars = consdata->vars;
10183 nvars = consdata->nvars;
10184
10185 assert(vars != NULL);
10186
10187 for( v = 0; v < nvars; ++v )
10188 {
10189 negated = FALSE;
10190 var = vars[v];
10191 assert(var != NULL);
10192
10193 if( SCIPvarIsNegated(var) )
10194 {
10195 negated = TRUE;
10196 var = SCIPvarGetNegatedVar(var);
10197 assert(var != NULL);
10198 }
10199
10200 objval = SCIPvarGetObj(var);
10201
10202 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10203 * function
10204 */
10205 if( SCIPisZero(scip, objval) )
10206 return FALSE;
10207 else
10208 {
10209 SCIP_Real val;
10210
10211 val = consdata->vals[v];
10212
10213 if( negated )
10214 {
10215 if( v == 0 )
10216 {
10217 /* the first variable defines the scale */
10218 (*scale) = val / -objval;
10219
10220 (*offset) += val;
10221 }
10222 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10223 (*offset) += val;
10224 else
10225 return FALSE;
10226 }
10227 else if( v == 0 )
10228 {
10229 /* the first variable defines the scale */
10230 (*scale) = val / objval;
10231 }
10232 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10233 return FALSE;
10234 }
10235 }
10236
10237 return TRUE;
10238}
10239
10240/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10241 * objective coefficients and add an objective offset
10242 */
10243static
10245 SCIP* scip, /**< SCIP data structure */
10246 SCIP_CONS* cons, /**< linear equation constraint */
10247 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10248 )
10249{
10250 SCIP_CONSDATA* consdata;
10251 SCIP_Real offset;
10252 SCIP_Real scale;
10253 SCIP_Bool applicable;
10254 int nobjvars;
10255 int nvars;
10256 int v;
10257
10258 assert(scip != NULL);
10259 assert(cons != NULL);
10260 assert(conshdlrdata != NULL);
10261
10262 consdata = SCIPconsGetData(cons);
10263 assert(consdata != NULL);
10264 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10265
10266 nvars = consdata->nvars;
10267 nobjvars = SCIPgetNObjVars(scip);
10268
10269 /* check if the linear equality constraints does not have more variables than the objective function */
10270 if( nvars > nobjvars || nvars == 0 )
10271 return SCIP_OKAY;
10272
10273 /* check for allowance of algorithm */
10274 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10275 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10276 return SCIP_OKAY;
10277
10278 offset = consdata->rhs;
10279 scale = 1.0;
10280
10281 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10282 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10283
10284 if( applicable )
10285 {
10286 SCIP_VAR** vars;
10287
10288 vars = consdata->vars;
10289 assert(vars != NULL);
10290
10291 offset /= scale;
10292
10293 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10294 SCIPconsGetName(cons), consdata->rhs, offset);
10295
10296 /* make equality a model constraint to ensure optimality in this direction */
10299
10300 /* set all objective coefficient to zero */
10301 for( v = 0; v < nvars; ++v )
10302 {
10303 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10304 }
10305
10306 /* add an objective offset */
10307 SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10308 }
10309
10310 return SCIP_OKAY;
10311}
10312
10313/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10314static
10316 SCIP* scip, /**< SCIP data structure */
10317 SCIP_CONS* cons, /**< constraint */
10318 SCIP_Real primalbound /**< feasible primal bound */
10319 )
10320{
10321 SCIP_Real cutoffbound;
10322
10323 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10324 * accepted
10325 */
10326 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10327
10328 if( cutoffbound < SCIPgetCutoffbound(scip) )
10329 {
10330 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10331
10332 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10333 }
10334 else
10335 {
10336 SCIP_CONSDATA* consdata;
10337
10338 consdata = SCIPconsGetData(cons);
10339 assert(consdata != NULL);
10340
10341 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10342 * resulted from one side
10343 */
10344 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10345 {
10346 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10347 * propagation
10348 */
10351 }
10352 }
10353
10354 return SCIP_OKAY;
10355}
10356
10357/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10358 * constraint enters the LP by setting the initial and separated flag to FALSE
10359 */
10360static
10362 SCIP* scip, /**< SCIP data structure */
10363 SCIP_CONS* cons, /**< linear constraint */
10364 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10365 )
10366{
10367 SCIP_CONSDATA* consdata;
10368 SCIP_Real offset;
10369 SCIP_Real scale;
10370 SCIP_Bool applicable;
10371 int nobjvars;
10372 int nvars;
10373
10374 assert(scip != NULL);
10375 assert(cons != NULL);
10376 assert(conshdlrdata != NULL);
10377
10378 consdata = SCIPconsGetData(cons);
10379 assert(consdata != NULL);
10380
10381 /* ignore equalities since these are covered by the method checkPartialObjective() */
10382 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10383 return SCIP_OKAY;
10384
10385 nvars = consdata->nvars;
10386 nobjvars = SCIPgetNObjVars(scip);
10387
10388 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10389 * initial and/or separated flag is set to FALSE
10390 */
10391 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10392 return SCIP_OKAY;
10393
10394 offset = 0.0;
10395 scale = 1.0;
10396
10397 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10398 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10399 */
10400 if( nobjvars == 0 )
10401 return SCIP_OKAY;
10402
10403 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10404 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10405
10406 if( applicable )
10407 {
10408 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10409 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10410
10411 assert(scale != 0.0);
10412
10413 if( scale > 0.0 )
10414 {
10415 if( conshdlrdata->detectcutoffbound && rhsfinite )
10416 {
10417 SCIP_Real primalbound;
10418
10419 primalbound = (consdata->rhs - offset) / scale;
10420
10421 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10422 SCIPconsGetName(cons), primalbound);
10423
10424 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10425 }
10426
10427 if( conshdlrdata->detectlowerbound && lhsfinite )
10428 {
10429 SCIP_Real lowerbound;
10430
10431 lowerbound = (consdata->lhs - offset) / scale;
10432
10433 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10434 SCIPconsGetName(cons), lowerbound);
10435
10437 }
10438
10439 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10440 (conshdlrdata->detectlowerbound && !rhsfinite) )
10441 {
10442 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10445 }
10446 }
10447 else
10448 {
10449 if( conshdlrdata->detectlowerbound && rhsfinite )
10450 {
10451 SCIP_Real lowerbound;
10452
10453 lowerbound = (consdata->rhs - offset) / scale;
10454
10455 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10456 SCIPconsGetName(cons), lowerbound);
10457
10459 }
10460
10461 if( conshdlrdata->detectcutoffbound && lhsfinite )
10462 {
10463 SCIP_Real primalbound;
10464
10465 primalbound = (consdata->lhs - offset) / scale;
10466
10467 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10468 SCIPconsGetName(cons), primalbound);
10469
10470 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10471 }
10472
10473 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10474 (conshdlrdata->detectlowerbound && !lhsfinite) )
10475 {
10476 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10479 }
10480 }
10481 }
10482
10483 return SCIP_OKAY;
10484}
10485
10486/** converts special equalities */
10487static
10489 SCIP* scip, /**< SCIP data structure */
10490 SCIP_CONS* cons, /**< linear constraint */
10491 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10492 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10493 int* nfixedvars, /**< pointer to count number of fixed variables */
10494 int* naggrvars, /**< pointer to count number of aggregated variables */
10495 int* ndelconss, /**< pointer to count number of deleted constraints */
10496 int* nchgvartypes /**< pointer to count number of changed variable types */
10497 )
10498{
10499 SCIP_CONSDATA* consdata;
10500
10501 assert(scip != NULL);
10502 assert(cons != NULL);
10503 assert(conshdlrdata != NULL);
10504 assert(cutoff != NULL);
10505 assert(nfixedvars != NULL);
10506 assert(naggrvars != NULL);
10507 assert(ndelconss != NULL);
10508
10509 consdata = SCIPconsGetData(cons);
10510 assert(consdata != NULL);
10511 assert(consdata->removedfixings);
10512
10513 /* do nothing on inequalities */
10514 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10515 return SCIP_OKAY;
10516
10517 /* depending on the number of variables, call a special conversion method */
10518 if( consdata->nvars == 1 )
10519 {
10520 /* fix variable */
10521 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10522 }
10523 else if( consdata->nvars == 2 )
10524 {
10525 /* aggregate one of the variables */
10526 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10527 }
10528 else
10529 {
10530 /* check if the equality is part of the objective function */
10531 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10532
10533 /* try to multi-aggregate one of the variables */
10534 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss, nchgvartypes) );
10535 }
10536
10537 return SCIP_OKAY;
10538}
10539
10540/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10541 * integral
10542 */
10543static
10545 SCIP* scip, /**< SCIP data structure */
10546 SCIP_CONSDATA* consdata, /**< linear constraint */
10547 int pos, /**< position of variable to be left out */
10548 SCIP_Real val /**< value to divide the coefficients by */
10549 )
10550{
10551 int v;
10552
10553 assert(scip != NULL);
10554 assert(consdata != NULL);
10555 assert(0 <= pos && pos < consdata->nvars);
10556
10557 for( v = 0; v < consdata->nvars; ++v )
10558 {
10559 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10560 return FALSE;
10561 }
10562
10563 return TRUE;
10564}
10565
10566/** 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$,
10567 * 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$
10568 */
10569static
10571 SCIP* scip, /**< SCIP data structure */
10572 SCIP_Real side, /**< lhs or rhs */
10573 SCIP_Real val, /**< coefficient */
10574 SCIP_Real minresactivity, /**< minimal residual activity */
10575 SCIP_Real maxresactivity, /**< maximal residual activity */
10576 SCIP_Real* minval, /**< pointer to store calculated minval */
10577 SCIP_Real* maxval /**< pointer to store calculated maxval */
10578 )
10579{
10580 assert(scip != NULL);
10581 assert(minval != NULL);
10582 assert(maxval != NULL);
10583
10584 if( val > 0.0 )
10585 {
10586 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10587 *minval = -maxresactivity;
10588 else
10589 *minval = (side - maxresactivity)/val;
10590
10591 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10592 *maxval = -minresactivity;
10593 else
10594 *maxval = (side - minresactivity)/val;
10595 }
10596 else
10597 {
10598 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10599 *minval = minresactivity;
10600 else
10601 *minval = (side - minresactivity)/val;
10602
10603 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10604 *maxval = maxresactivity;
10605 else
10606 *maxval = (side - maxresactivity)/val;
10607 }
10608}
10609
10610
10611/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10612 * linear inequality
10613 */
10614static
10616 SCIP* scip, /**< SCIP data structure */
10617 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10618 SCIP_CONS* cons, /**< linear constraint */
10619 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10620 int* nfixedvars, /**< pointer to count number of fixed variables */
10621 int* naggrvars, /**< pointer to count number of aggregated variables */
10622 int* ndelconss, /**< pointer to count number of deleted constraints */
10623 int* nchgvartypes /**< pointer to count number of changed variable types */
10624 )
10625{
10626 SCIP_CONSDATA* consdata;
10627 SCIP_Bool lhsexists;
10628 SCIP_Bool rhsexists;
10629 SCIP_Bool bestisint;
10630 SCIP_Bool bestislhs;
10631 SCIP_Real minabsval;
10632 SCIP_Real maxabsval;
10633 int bestpos;
10634 int i;
10635 int maxotherlocks;
10636
10637 assert(scip != NULL);
10638 assert(cons != NULL);
10639 assert(cutoff != NULL);
10640 assert(nfixedvars != NULL);
10641 assert(naggrvars != NULL);
10642 assert(ndelconss != NULL);
10643
10644 /* only process checked constraints (for which the locks are increased);
10645 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10646 * dualfix presolver
10647 */
10648 if( !SCIPconsIsChecked(cons) )
10649 return SCIP_OKAY;
10650
10651 consdata = SCIPconsGetData(cons);
10652 assert(consdata != NULL);
10653
10654 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10655 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10656
10657 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10658 * can use it safely for aggregation and break the search loop
10659 */
10660 bestpos = -1;
10661 bestisint = TRUE;
10662 bestislhs = FALSE;
10663
10664 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10665 * everything else would produce fill-in. Exceptions:
10666 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10667 * produced.
10668 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10669 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10670 * six nonzeros (two variables per substitution).
10671 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10672 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10673 * six nonzeros (three variables per substitution). God exists!
10674 */
10675 if( consdata->nvars <= 2 )
10676 maxotherlocks = INT_MAX;
10677 else if( consdata->nvars == 3 )
10678 maxotherlocks = 3;
10679 else if( consdata->nvars == 4 )
10680 maxotherlocks = 2;
10681 else
10682 maxotherlocks = 1;
10683
10684 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10685 if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10686 maxotherlocks++;
10687
10688 minabsval = SCIPinfinity(scip);
10689 maxabsval = -1.0;
10690 for( i = 0; i < consdata->nvars && bestisint; ++i )
10691 {
10692 SCIP_VAR* var;
10693 SCIP_Bool isint;
10694 SCIP_Real val;
10695 SCIP_Real absval;
10696 SCIP_Real obj;
10697 SCIP_Real lb;
10698 SCIP_Real ub;
10699 SCIP_Bool agglhs;
10700 SCIP_Bool aggrhs;
10701
10702 val = consdata->vals[i];
10703 absval = REALABS(val);
10704
10705 /* calculate minimal and maximal absolute value */
10706 if( absval < minabsval )
10707 minabsval = absval;
10708 if( absval > maxabsval )
10709 maxabsval = absval;
10710
10711 /* do not try to multi aggregate, when numerical bad */
10712 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10713 return SCIP_OKAY;
10714
10715 var = consdata->vars[i];
10717
10718 /* if we already found a candidate, skip integers */
10719 if( bestpos >= 0 && isint )
10720 continue;
10721
10722 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10723 * active, fixed, or single-aggregated with another binary variable
10724 */
10725 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10726 continue;
10727
10728 if ( SCIPdoNotMultaggrVar(scip, var) )
10729 continue;
10730
10731 val = consdata->vals[i];
10732 obj = SCIPvarGetObj(var);
10733 lb = SCIPvarGetLbGlobal(var);
10734 ub = SCIPvarGetUbGlobal(var);
10735
10736 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10737 *
10738 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10739 * - constraint is the only one that forbids fixing the variable to its lower bound
10740 * - fix x_i to the smallest value for this constraint: x_i := lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
10741 *
10742 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10743 * - constraint is the only one that forbids fixing the variable to its upper bound
10744 * - 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
10745 *
10746 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10747 * - constraint is the only one that forbids fixing the variable to its upper bound
10748 * - 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
10749 *
10750 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10751 * - constraint is the only one that forbids fixing the variable to its lower bound
10752 * - 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
10753 *
10754 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10755 * of all x_j
10756 * furthermore: we only want to apply this, if no fill-in will be produced
10757 */
10758 agglhs = lhsexists
10759 && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10760 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10761 || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10762 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10763 aggrhs = rhsexists
10764 && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10765 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10766 || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10767 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10768 if( agglhs || aggrhs )
10769 {
10770 SCIP_Real minresactivity;
10771 SCIP_Real maxresactivity;
10772 SCIP_Real minval;
10773 SCIP_Real maxval;
10774 SCIP_Bool ismintight;
10775 SCIP_Bool ismaxtight;
10776 SCIP_Bool isminsettoinfinity;
10777 SCIP_Bool ismaxsettoinfinity;
10778
10779 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10780 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10781 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
10782 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10783
10784 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10785 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10786 * This is needed, because we do not want to rely on relaxed finite resactivities.
10787 */
10788 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
10789
10790 if( agglhs )
10791 {
10792 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10793 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10794
10795 assert(SCIPisLE(scip, minval, maxval));
10796 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10797 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10798 {
10799 SCIP_Real oldmaxresactivity;
10800 SCIP_Real oldminresactivity;
10801 SCIP_Bool recalculated;
10802
10803 recalculated = FALSE;
10804 oldmaxresactivity = maxresactivity;
10805 oldminresactivity = minresactivity;
10806
10807 /* check minresactivity for reliability */
10808 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10809 {
10810 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10811 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10812 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10813 }
10814
10815 /* check maxresactivity for reliability */
10816 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10817 {
10818 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10819 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10820 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10821 }
10822
10823 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10824 if( recalculated )
10825 {
10826 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10827
10828 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10829 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10830
10831 assert(SCIPisLE(scip, minval, maxval));
10832 }
10833
10834 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10835 {
10836 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10837 * in the multi-aggregation
10838 */
10839 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10840 {
10841 bestpos = i;
10842 bestisint = isint;
10843 bestislhs = TRUE;
10844 continue; /* no need to also look at the right hand side */
10845 }
10846 }
10847 }
10848 }
10849
10850 if( aggrhs )
10851 {
10852 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10853 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10854
10855 assert(SCIPisLE(scip,minval,maxval));
10856 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10857 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10858 {
10859 SCIP_Real oldmaxresactivity;
10860 SCIP_Real oldminresactivity;
10861 SCIP_Bool recalculated;
10862
10863 recalculated = FALSE;
10864 oldmaxresactivity = maxresactivity;
10865 oldminresactivity = minresactivity;
10866
10867 /* check minresactivity for reliability */
10868 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10869 {
10870 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10871 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10872 }
10873
10874 /* check maxresactivity for reliability */
10875 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10876 {
10877 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10878 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10879 }
10880
10881 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10882 if( recalculated )
10883 {
10884 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10885 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10886 assert(SCIPisLE(scip,minval,maxval));
10887 }
10888
10889 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10890 {
10891 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10892 * in the multi-aggregation
10893 */
10894 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10895 {
10896 bestpos = i;
10897 bestisint = isint;
10898 bestislhs = FALSE;
10899 }
10900 }
10901 }
10902 }
10903 }
10904 }
10905
10906 if( bestpos >= 0 )
10907 {
10908 SCIP_VAR** aggrvars;
10909 SCIP_Real* aggrcoefs;
10910 SCIP_Real aggrconst;
10911 SCIP_VAR* bestvar;
10912 SCIP_Real bestval;
10913 SCIP_Real epsilon;
10914 int naggrs;
10915 int j;
10916 SCIP_Bool infeasible;
10917 SCIP_Bool aggregated;
10918 SCIP_Bool samevar;
10919 int supinf; /* counter for infinite contributions to the supremum of a possible
10920 * multi-aggregation
10921 */
10922 int infinf; /* counter for infinite contributions to the infimum of a possible
10923 * multi-aggregation
10924 */
10925
10926 assert(!bestislhs || lhsexists);
10927 assert(bestislhs || rhsexists);
10928
10929 bestvar = consdata->vars[bestpos];
10930 bestval = consdata->vals[bestpos];
10931 assert(bestisint ==
10933
10934 /* allocate temporary memory */
10935 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10936 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10937
10938 /* set up the multi-aggregation */
10940 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10941 naggrs = 0;
10942 supinf = 0;
10943 infinf = 0;
10944 samevar = FALSE;
10945 epsilon = SCIPepsilon(scip);
10946
10947 for( j = 0; j < consdata->nvars; ++j )
10948 {
10949 if( j != bestpos )
10950 {
10951 SCIP_Real absaggrcoef;
10952
10953 aggrvars[naggrs] = consdata->vars[j];
10954 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10955 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10956
10957 absaggrcoef = REALABS(aggrcoefs[naggrs]);
10958
10959 /* do not try to multi aggregate, when numerical bad */
10960 if( absaggrcoef < epsilon )
10961 {
10962 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10963
10964 /* free temporary memory */
10965 SCIPfreeBufferArray(scip, &aggrcoefs);
10966 SCIPfreeBufferArray(scip, &aggrvars);
10967
10968 return SCIP_OKAY;
10969 }
10970
10971 if( bestisint )
10972 {
10973 /* coefficient must be integral: round it to exact integral value */
10974 assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10975 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10976 }
10977
10978 if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10979 {
10980 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10981 {
10982 ++supinf;
10983 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10984 {
10985 ++infinf;
10986 samevar = TRUE;
10987 }
10988 }
10989 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10990 ++infinf;
10991 }
10992 else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
10993 {
10994 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10995 {
10996 ++supinf;
10997 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10998 {
10999 ++infinf;
11000 samevar = TRUE;
11001 }
11002 }
11003 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11004 ++infinf;
11005 }
11006
11007 naggrs++;
11008 }
11009 }
11010 assert(!samevar || (supinf > 0 && infinf > 0));
11011
11012 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11013 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11014 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
11015 assert(naggrs == consdata->nvars-1);
11016
11017 /* right hand side must be integral: round it to exact integral value */
11018 if( bestisint )
11019 {
11020 assert(SCIPisIntegral(scip, aggrconst));
11021 aggrconst = SCIPfloor(scip, aggrconst+0.5);
11022 }
11023
11024 aggregated = FALSE;
11025 infeasible = FALSE;
11026
11027 /* perform the multi-aggregation */
11028 if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11029 {
11030 /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11031 * also convertLongEquality() early termination due to coefficients
11032 */
11033 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11034
11035 /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11036 * the implicitness might rely on the constraint and the integrality of bestvar
11037 */
11038 if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11039 {
11040 SCIP_Bool infeasiblevartypechg;
11041
11042 for( j = 0; j < naggrs; ++j)
11043 {
11044 /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11045 * lead to infeasibility
11046 */
11047 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT )
11048 {
11049 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
11050 (*nchgvartypes)++;
11051 assert(!infeasiblevartypechg);
11052 }
11053 }
11054 }
11055 }
11056 else
11057 {
11058 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11059 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11060 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11061 }
11062 /* free temporary memory */
11063 SCIPfreeBufferArray(scip, &aggrcoefs);
11064 SCIPfreeBufferArray(scip, &aggrvars);
11065
11066 /* check for infeasible aggregation */
11067 if( infeasible )
11068 {
11069 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11070 *cutoff = TRUE;
11071 return SCIP_OKAY;
11072 }
11073
11074 /* delete the constraint, if the aggregation was successful */
11075 if( aggregated )
11076 {
11077 SCIP_CALL( SCIPdelCons(scip, cons) );
11078
11079 if( !consdata->upgraded )
11080 (*ndelconss)++;
11081 (*naggrvars)++;
11082 }
11083 else
11084 {
11085 SCIPdebugMsg(scip, "aggregation non successful!\n");
11086 }
11087 }
11088
11089 return SCIP_OKAY;
11090}
11091
11092#define BINWEIGHT 1
11093#define INTWEIGHT 4
11094#define CONTWEIGHT 8
11095
11096/** gets weight for variable in a "weighted number of variables" sum */
11097static
11099 SCIP_VAR* var /**< variable to get weight for */
11100 )
11101{
11102 switch( SCIPvarGetType(var) )
11103 {
11105 return BINWEIGHT;
11108 return INTWEIGHT;
11110 return CONTWEIGHT;
11111 default:
11112 SCIPerrorMessage("invalid variable type\n");
11113 SCIPABORT();
11114 return 0; /*lint !e527*/
11115 }
11116}
11117
11118/** tries to aggregate variables in equations a^Tx = lhs
11119 * in case there are at most two binary variables with an odd coefficient and all other
11120 * variables are not continuous and have an even coefficient then:
11121 * - exactly one odd binary variables
11122 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11123 * - lhs is odd -> y = 1
11124 * - lhs is even -> y = 0
11125 * - exactly two odd binary variables
11126 * aggregate the two binary variables with odd coefficient
11127 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11128 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11129 */
11130static
11132 SCIP* scip, /**< SCIP data structure */
11133 SCIP_CONS* cons, /**< linear constraint */
11134 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11135 int* nfixedvars, /**< pointer to count number of fixed variables */
11136 int* naggrvars /**< pointer to count number of aggregated variables */
11137 )
11138{ /*lint --e{715}*/
11139 SCIP_CONSDATA* consdata;
11140 SCIP_Bool success;
11141
11142 assert( scip != NULL );
11143 assert( cons != NULL );
11144
11145 consdata = SCIPconsGetData(cons);
11146 assert( consdata != NULL );
11147
11148 /* check if the linear constraint is an equation with integral right hand side */
11149 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11150 return SCIP_OKAY;
11151
11152 /* try to fix and aggregated variables until nothing is possible anymore */
11153 do
11154 {
11155 int v;
11156 int nvars;
11157 SCIP_VAR** vars;
11158 SCIP_Real* vals;
11159 SCIP_Real lhs;
11160 SCIP_Bool lhsodd;
11161
11162 SCIP_Bool infeasible;
11163 SCIP_Bool fixed;
11164 SCIP_Bool aggregated;
11165 SCIP_Bool redundant;
11166
11167 SCIP_VAR* var1;
11168 SCIP_VAR* var2;
11169 int noddvars;
11170
11171 success = FALSE;
11172
11173 lhs = consdata->lhs;
11174 vars = consdata->vars;
11175 vals = consdata->vals;
11176 nvars = consdata->nvars;
11177
11178 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11179
11180 var1 = NULL;
11181 var2 = NULL;
11182 noddvars = 0;
11183
11184 /* search for binary variables with an odd coefficient */
11185 for( v = 0; v < nvars && noddvars < 3; ++v )
11186 {
11187 SCIP_Longint val;
11188
11189 /* all coefficients and variables have to be integral */
11190 if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11191 return SCIP_OKAY;
11192
11193 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11194 if( val % 2 != 0 )
11195 {
11196 /* the odd values have to belong to binary variables */
11197 if( !SCIPvarIsBinary(vars[v]) )
11198 return SCIP_OKAY;
11199
11200 if( noddvars == 0 )
11201 var1 = vars[v];
11202 else
11203 var2 = vars[v];
11204
11205 noddvars++;
11206 }
11207 }
11208
11209 /* check lhs is odd or even */
11210 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11211
11212 if( noddvars == 1 )
11213 {
11214 assert( var1 != NULL );
11215
11216 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11217 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11218
11219 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11220
11221 /* check for infeasibility of fixing */
11222 if( infeasible )
11223 {
11224 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11225 *cutoff = TRUE;
11226 return SCIP_OKAY;
11227 }
11228
11229 if( fixed )
11230 {
11231 SCIPdebugMsg(scip, " -> feasible fixing\n");
11232 (*nfixedvars)++;
11233 success = TRUE;
11234 }
11235 }
11236 else if( noddvars == 2 )
11237 {
11238 assert( var1 != NULL );
11239 assert( var2 != NULL );
11240
11241 /* aggregate the two variables with odd coefficient
11242 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11243 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11244 */
11245 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11246 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11247
11248 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11249 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11250
11251 /* check for infeasibility of aggregation */
11252 if( infeasible )
11253 {
11254 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11255 *cutoff = TRUE;
11256 return SCIP_OKAY;
11257 }
11258
11259 /* count the aggregation */
11260 if( aggregated )
11261 {
11262 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11263 (*naggrvars)++;
11264 success = TRUE;
11265 }
11266 }
11267
11268 if( success )
11269 {
11270 /* apply fixings and aggregation to successfully rerun this presolving step */
11271 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11272
11273 if( infeasible )
11274 {
11275 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11276 *cutoff = TRUE;
11277 return SCIP_OKAY;
11278 }
11279
11280 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11281
11282 if( infeasible )
11283 {
11284 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11285 *cutoff = TRUE;
11286 return SCIP_OKAY;
11287 }
11288 }
11289 }
11290 while( success && consdata->nvars >= 1 );
11291
11292 return SCIP_OKAY;
11293}
11294
11295
11296
11297/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11298 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11299 * coefficients
11300 */
11301static
11303{ /*lint --e{715}*/
11304 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11305 SCIP_VARTYPE vartype1;
11306 SCIP_VARTYPE vartype2;
11307 SCIP_Real value;
11308
11309 assert(consdata != NULL);
11310 assert(0 <= ind1 && ind1 < consdata->nvars);
11311 assert(0 <= ind2 && ind2 < consdata->nvars);
11312
11313 vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11314 vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11315
11316 if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11317 {
11318 /* continuous varibles will be sorted to the back */
11319 if( vartype2 != vartype1 )
11320 return +1;
11321 /* both variables are continuous */
11322 else
11323 return 0;
11324 }
11325 /* continuous variables will be sorted to the back */
11326 else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11327 return -1;
11328
11329 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11330
11331 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11332 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11333}
11334
11335/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11336 *
11337 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11338 * then we can change this constraint to 1^Tx = 1
11339 */
11340static
11342 SCIP* scip, /**< SCIP data structure */
11343 SCIP_CONS* cons, /**< linear constraint */
11344 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11345 int* nchgsides /**< pointer to store the amount of changed sides */
11346 )
11347{
11348 SCIP_CONSDATA* consdata;
11349 SCIP_VAR** vars;
11350 SCIP_Real* vals;
11351 SCIP_Real minval;
11352 SCIP_Real secondminval;
11353 SCIP_Real maxval;
11354 SCIP_Real lhs;
11355 SCIP_Real rhs;
11356 int nvars;
11357 int v;
11358
11359 /* we must not change a modifiable constraint in any way */
11360 if( SCIPconsIsModifiable(cons) )
11361 return SCIP_OKAY;
11362
11363 if( SCIPconsIsDeleted(cons) )
11364 return SCIP_OKAY;
11365
11366 consdata = SCIPconsGetData(cons);
11367 assert(consdata != NULL);
11368
11369 nvars = consdata->nvars;
11370
11371 /* do not check empty or bound-constraints */
11372 if( nvars < 2 )
11373 return SCIP_OKAY;
11374
11375 lhs = consdata->lhs;
11376 rhs = consdata->rhs;
11377 assert(!SCIPisInfinity(scip, -lhs));
11378 assert(!SCIPisInfinity(scip, rhs));
11379 assert(!SCIPisNegative(scip, rhs));
11380
11381 /* sides must be positive and different to detect set partition */
11382 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11383 return SCIP_OKAY;
11384
11385 vals = consdata->vals;
11386 vars = consdata->vars;
11387 assert(vars != NULL);
11388 assert(vals != NULL);
11389
11390 minval = SCIP_INVALID;
11391 secondminval = SCIP_INVALID;
11392 maxval = -SCIP_INVALID;
11393
11394 for( v = nvars - 1; v >= 0; --v )
11395 {
11396 if( SCIPvarIsBinary(vars[v]) )
11397 {
11398 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11399 {
11400 secondminval = minval;
11401 minval = vals[v];
11402 }
11403 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11404 secondminval = vals[v];
11405
11406 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11407 maxval = vals[v];
11408 }
11409 else
11410 break;
11411 }
11412
11413 /* check if all variables are binary, we can choose one, and need to choose at most one */
11414 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11415 && SCIPisGT(scip, minval + secondminval, rhs) )
11416 {
11417 /* change all coefficients to 1.0 */
11418 for( v = nvars - 1; v >= 0; --v )
11419 {
11420 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11421 }
11422 (*nchgcoefs) += nvars;
11423
11424 /* replace old right and left hand side with 1.0 */
11425 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11426 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11427 (*nchgsides) += 2;
11428 }
11429
11430 return SCIP_OKAY;
11431}
11432
11433/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11434 *
11435 * for both-sided constraints only @see rangedRowSimplify() will be called
11436 *
11437 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11438 *
11439 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11440 *
11441 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11442 *
11443 * 2. We try to remove redundant fractional parts in a constraint
11444 *
11445 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11446 *
11447 * 3. We are using the greatest common divisor for further reductions
11448 *
11449 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11450 * integral
11451 */
11452static
11454 SCIP* scip, /**< SCIP data structure */
11455 SCIP_CONS* cons, /**< linear constraint */
11456 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11457 int* nchgsides, /**< pointer to store the amount of changed sides */
11458 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11459 )
11460{
11461 SCIP_CONSDATA* consdata;
11462 SCIP_VAR** vars;
11463 SCIP_Real* vals;
11464 int* perm;
11465 SCIP_Real minactsub;
11466 SCIP_Real maxactsub;
11467 SCIP_Real siderest;
11468 SCIP_Real feastol;
11469 SCIP_Real newcoef;
11470 SCIP_Real absval;
11471 SCIP_Real minact;
11472 SCIP_Real maxact;
11473 SCIP_Real side;
11474 SCIP_Real lhs;
11475 SCIP_Real rhs;
11476 SCIP_Real lb;
11477 SCIP_Real ub;
11478 SCIP_Longint restcoef;
11479 SCIP_Longint oldgcd;
11480 SCIP_Longint rest;
11481 SCIP_Longint gcd;
11482 SCIP_Bool isminsettoinfinity;
11483 SCIP_Bool ismaxsettoinfinity;
11484 SCIP_Bool ismintight;
11485 SCIP_Bool ismaxtight;
11486 SCIP_Bool allcoefintegral;
11487 SCIP_Bool onlybin;
11488 SCIP_Bool hasrhs;
11489 SCIP_Bool haslhs;
11490 int oldnchgcoefs;
11491 int oldnchgsides;
11492 int foundbin;
11493 int candpos;
11494 int candpos2;
11495 int offsetv;
11496 int nvars;
11497 int v;
11498 int w;
11499
11500 assert(scip != NULL);
11501 assert(cons != NULL);
11502 assert(nchgcoefs != NULL);
11503 assert(nchgsides != NULL);
11504
11505 *infeasible = FALSE;
11506
11507 /* we must not change a modifiable constraint in any way */
11508 if( SCIPconsIsModifiable(cons) )
11509 return SCIP_OKAY;
11510
11511 if( SCIPconsIsDeleted(cons) )
11512 return SCIP_OKAY;
11513
11514 consdata = SCIPconsGetData(cons);
11515 assert(consdata != NULL);
11516
11517 nvars = consdata->nvars;
11518
11519 /* do not check empty or bound-constraints */
11520 if( nvars <= 2 )
11521 return SCIP_OKAY;
11522
11523 /* update maximal activity delta if necessary */
11524 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11526
11527 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11528 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11529 checkMaxActivityDelta(scip, consdata);
11530
11531 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11532 * accordingly
11533 */
11534 /* can only work with valid non-infinity activities per variable */
11535 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11536 return SCIP_OKAY;
11537
11538 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11539 * but the eventsystem seems to be full
11540 */
11541 consdata->normalized = FALSE;
11542
11543 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11544 assert(nvars == consdata->nvars);
11545
11546 if( *infeasible )
11547 return SCIP_OKAY;
11548
11549 if( !consdata->normalized )
11550 return SCIP_OKAY;
11551
11552 lhs = consdata->lhs;
11553 rhs = consdata->rhs;
11554 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11555 assert(!SCIPisNegative(scip, rhs));
11556
11557 if( !SCIPisInfinity(scip, -lhs) )
11558 haslhs = TRUE;
11559 else
11560 haslhs = FALSE;
11561
11562 if( !SCIPisInfinity(scip, rhs) )
11563 hasrhs = TRUE;
11564 else
11565 hasrhs = FALSE;
11566
11567 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11568 SCIPdebug( oldnchgsides = *nchgsides; )
11569
11570 /* @todo extend both-sided simplification */
11571 if( haslhs && hasrhs )
11572 {
11573 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11574
11575 return SCIP_OKAY;
11576 }
11577 assert(haslhs != hasrhs);
11578
11579 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11580 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11581 assert(!haslhs || !SCIPisNegative(scip, lhs));
11582
11583 /* get temporary memory to store the sorted permutation */
11584 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11585
11586 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11587 * value of their coefficients
11588 */
11589 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11590
11591 /* perform sorting after permutation array */
11592 permSortConsdata(consdata, perm, nvars);
11593 consdata->indexsorted = FALSE;
11594 consdata->coefsorted = FALSE;
11595
11596 vars = consdata->vars;
11597 vals = consdata->vals;
11598 assert(vars != NULL);
11599 assert(vals != NULL);
11600 assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11601
11602 /* free temporary memory */
11603 SCIPfreeBufferArray(scip, &perm);
11604
11605 /* only check constraints with at least two non continuous variables */
11606 if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11607 return SCIP_OKAY;
11608
11609 /* do not process constraints when all coefficients are 1.0 */
11610 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11611 return SCIP_OKAY;
11612
11613 feastol = SCIPfeastol(scip);
11614
11615 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11617
11618 /* get global activities */
11619 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11620 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
11621
11622 /* cannot work with infinite activities */
11623 if( isminsettoinfinity || ismaxsettoinfinity )
11624 return SCIP_OKAY;
11625
11626 assert(ismintight);
11627 assert(ismaxtight);
11628 assert(maxact > minact);
11629 assert(!SCIPisInfinity(scip, -minact));
11630 assert(!SCIPisInfinity(scip, maxact));
11631
11632 v = 0;
11633 offsetv = -1;
11634 side = haslhs ? lhs : rhs;
11635 minactsub = minact;
11636 maxactsub = maxact;
11637
11638 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11639 * do not need to look at the large coefficients
11640 *
11641 * e.g. all x are binary, z are positive integer
11642 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11643 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11644 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11645 *
11646 * can be changed to
11647 *
11648 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11649 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11650 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11651 */
11652
11653 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11654 * hand side, we cannot apply the extra reduction step and need to reset v
11655 *
11656 * 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
11657 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11658 * for all i is a solution
11659 *
11660 * also redundancy of variables would not be correctly determined in such a case
11661 */
11662 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11663 {
11664 v = 1;
11665
11666 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11667 {
11668 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11669 * extra step, which might have worked
11670 */
11671 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11672 {
11673 v = 0;
11674 break;
11675 }
11676
11677 ++v;
11678 }
11679
11680 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11681 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11682 if( v == nvars )
11683 return SCIP_OKAY;
11684
11685 /* cannot work with continuous variables which have a big coefficient */
11686 if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11687 return SCIP_OKAY;
11688
11689 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11690 if( SCIPisEQ(scip, side, -vals[v]) )
11691 v = 0;
11692
11693 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11694 * reduction
11695 */
11696 if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11697 v = 0;
11698
11699 if( v > 0 )
11700 {
11701 assert(v < nvars);
11702
11703 offsetv = v - 1;
11704
11705 for( w = 0; w < v; ++w )
11706 {
11707 lb = SCIPvarGetLbGlobal(vars[w]);
11708 ub = SCIPvarGetUbGlobal(vars[w]);
11709
11710 assert(vals[w] > 0);
11711
11712 /* update residual activities */
11713 maxactsub -= ub * vals[w];
11714 minactsub -= lb * vals[w];
11715 assert(maxactsub > minactsub);
11716 }
11717 }
11718 }
11719
11720 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11721 *
11722 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11723 *
11724 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11725 * to
11726 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11727 */
11728 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11729 {
11730 SCIP_Bool redundant = FALSE;
11731 SCIP_Bool numericsok;
11732 SCIP_Bool rredundant;
11733 SCIP_Bool lredundant;
11734
11735 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11736 assert(gcd >= 1);
11737
11738 if( v == 0 )
11739 {
11740 lb = SCIPvarGetLbGlobal(vars[0]);
11741 ub = SCIPvarGetUbGlobal(vars[0]);
11742
11743 /* update residual activities */
11744 if( vals[0] > 0 )
11745 {
11746 maxactsub -= ub * vals[0];
11747 minactsub -= lb * vals[0];
11748 }
11749 else
11750 {
11751 maxactsub -= lb * vals[0];
11752 minactsub -= ub * vals[0];
11753 }
11754 assert(maxactsub > minactsub);
11755 ++v;
11756 }
11757
11758 siderest = -SCIP_INVALID;
11759 allcoefintegral = TRUE;
11760
11761 /* check if some variables always fit into the given constraint */
11762 for( ; v < nvars - 1; ++v )
11763 {
11764 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11765 break;
11766
11767 if( !SCIPisIntegral(scip, vals[v]) )
11768 {
11769 allcoefintegral = FALSE;
11770 break;
11771 }
11772
11773 /* calculate greatest common divisor for all general and binary variables */
11774 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11775
11776 if( gcd == 1 )
11777 break;
11778
11779 lb = SCIPvarGetLbGlobal(vars[v]);
11780 ub = SCIPvarGetUbGlobal(vars[v]);
11781
11782 assert(!SCIPisInfinity(scip, -lb));
11783 assert(!SCIPisInfinity(scip, ub));
11784
11785 /* update residual activities */
11786 if( vals[v] > 0 )
11787 {
11788 maxactsub -= ub * vals[v];
11789 minactsub -= lb * vals[v];
11790 }
11791 else
11792 {
11793 maxactsub -= lb * vals[v];
11794 minactsub -= ub * vals[v];
11795 }
11796 assert(SCIPisGE(scip, maxactsub, minactsub));
11797
11798 if( hasrhs )
11799 {
11800 /* determine the remainder of the right hand side and the gcd */
11801 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11802 }
11803 else
11804 {
11805 /* determine the remainder of the left hand side and the gcd */
11806 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11807 if( SCIPisZero(scip, siderest) )
11808 siderest = gcd;
11809 }
11810
11811 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11812 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11813
11814 /* early termination if the activities deceed the gcd */
11815 if( offsetv == -1 && (rredundant || lredundant) )
11816 {
11817 redundant = TRUE;
11818 break;
11819 }
11820 }
11821 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11822
11823 if( !redundant )
11824 {
11825 if( hasrhs )
11826 {
11827 /* determine the remainder of the right hand side and the gcd */
11828 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11829 }
11830 else
11831 {
11832 /* determine the remainder of the left hand side and the gcd */
11833 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11834 if( SCIPisZero(scip, siderest) )
11835 siderest = gcd;
11836 }
11837 }
11838 else
11839 ++v;
11840
11841 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",
11842 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11843
11844 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11845 * reasonable absolute values */
11846 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11847 REALABS(minactsub) < MAXACTVAL;
11848
11849 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11850 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11851
11852 /* check if we can remove redundant variables */
11853 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11854 {
11855 SCIP_Real oldcoef;
11856
11857 /* double check the redundancy */
11858#ifndef NDEBUG
11859 SCIP_Real tmpminactsub = 0.0;
11860 SCIP_Real tmpmaxactsub = 0.0;
11861
11862 /* recompute residual activities */
11863 for( w = v; w < nvars; ++w )
11864 {
11865 lb = SCIPvarGetLbGlobal(vars[w]);
11866 ub = SCIPvarGetUbGlobal(vars[w]);
11867
11868 assert(!SCIPisInfinity(scip, -lb));
11869 assert(!SCIPisInfinity(scip, ub));
11870
11871 /* update residual activities */
11872 if( vals[w] > 0 )
11873 {
11874 tmpmaxactsub += ub * vals[w];
11875 tmpminactsub += lb * vals[w];
11876 }
11877 else
11878 {
11879 tmpmaxactsub += lb * vals[w];
11880 tmpminactsub += ub * vals[w];
11881 }
11882 assert(tmpmaxactsub >= tmpminactsub);
11883 }
11884
11885 if( hasrhs )
11886 {
11887 assert(offsetv == -1);
11888
11889 /* determine the remainder of the right hand side and the gcd */
11890 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11891 }
11892 else
11893 {
11894 /* determine the remainder of the left hand side and the gcd */
11895 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11896 if( SCIPisZero(scip, siderest) )
11897 siderest = gcd;
11898 }
11899
11900 /* is the redundancy really fulfilled */
11901 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11902 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11903#endif
11904
11905 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11906 nvars - v, SCIPconsGetName(cons));
11907
11908 /* remove redundant variables */
11909 for( w = nvars - 1; w >= v; --w )
11910 {
11911 SCIP_CALL( delCoefPos(scip, cons, w) );
11912 }
11913 (*nchgcoefs) += (nvars - v);
11914
11915 assert(w >= 0);
11916
11917 oldcoef = vals[w];
11918
11919 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11920 assert(vars == consdata->vars);
11921 assert(vals == consdata->vals);
11922 assert(w < consdata->nvars);
11923
11924 if( *infeasible )
11925 return SCIP_OKAY;
11926
11927 /* compute new greatest common divisor due to normalization */
11928 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11929 assert(gcd >= 1);
11930
11931 /* update side */
11932 if( hasrhs )
11933 {
11934 /* replace old with new right hand side */
11935 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11936 rhs = consdata->rhs;
11937 }
11938 else
11939 {
11940 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11941 {
11942 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11943 lhs = consdata->lhs;
11944 }
11945 else
11946 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11947 }
11948 ++(*nchgsides);
11949
11950 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11951 assert(!haslhs || !SCIPisNegative(scip, lhs));
11952
11953 /* get new constraint data */
11954 nvars = consdata->nvars;
11955 assert(nvars > 0);
11956
11957 allcoefintegral = TRUE;
11958
11959#ifndef NDEBUG
11960 /* check integrality */
11961 for( w = offsetv + 1; w < nvars; ++w )
11962 {
11963 assert(SCIPisIntegral(scip, vals[w]));
11964 }
11965#endif
11967 }
11968
11969 /* try to find a better gcd, when having large coefficients */
11970 if( offsetv >= 0 && gcd == 1 )
11971 {
11972 /* calculate greatest common divisor for all general variables */
11973 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11974
11975 if( gcd > 1 )
11976 {
11977 gcd = -1;
11978 candpos = -1;
11979
11980 for( v = nvars - 1; v > offsetv; --v )
11981 {
11982 assert(!SCIPisZero(scip, vals[v]));
11983 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11984 break;
11985
11986 if( !SCIPisIntegral(scip, vals[v]) )
11987 {
11988 allcoefintegral = FALSE;
11989 break;
11990 }
11991
11992 oldgcd = gcd;
11993
11994 if( gcd == -1 )
11995 {
11996 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11997 assert(gcd >= 1);
11998 }
11999 else
12000 {
12001 /* calculate greatest common divisor for all general and binary variables */
12002 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12003 }
12004
12005 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12006 * can stop searching
12007 */
12008 if( gcd == 1 )
12009 {
12010 if( !SCIPvarIsBinary(vars[v]) )
12011 break;
12012
12013 /* found candidate */
12014 if( candpos == -1 )
12015 {
12016 gcd = oldgcd;
12017 candpos = v;
12018 }
12019 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12020 else
12021 break;
12022 }
12023 }
12024 assert(v > offsetv || candpos > offsetv);
12025 }
12026 else
12027 candpos = -1;
12028 }
12029 else
12030 candpos = nvars - 1;
12031
12032 /* check last coefficient for integrality */
12033 if( gcd > 1 && allcoefintegral && !redundant )
12034 {
12035 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12036 allcoefintegral = FALSE;
12037 }
12038
12039 /* check for further necessary coefficient adjustments */
12040 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12041 {
12042 assert(offsetv + 1 < nvars);
12043 assert(0 <= candpos && candpos < nvars);
12044
12045 if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12046 {
12047 SCIP_Bool notchangable = FALSE;
12048
12049#ifndef NDEBUG
12050 /* check integrality */
12051 for( w = offsetv + 1; w < nvars; ++w )
12052 {
12053 assert(SCIPisIntegral(scip, vals[w]));
12054 }
12055#endif
12056
12057 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12058 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12059 {
12060 /* determine the remainder of the side and the gcd */
12061 if( hasrhs )
12062 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12063 else
12064 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12065 assert(rest >= 0);
12066 assert(rest < gcd);
12067
12068 /* determine the remainder of the coefficient candidate and the gcd */
12069 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12070 assert(restcoef >= 1);
12071 assert(restcoef < gcd);
12072
12073 if( hasrhs )
12074 {
12075 /* calculate new coefficient */
12076 if( restcoef > rest )
12077 newcoef = vals[candpos] - restcoef + gcd;
12078 else
12079 newcoef = vals[candpos] - restcoef;
12080 }
12081 else
12082 {
12083 /* calculate new coefficient */
12084 if( rest == 0 || restcoef < rest )
12085 newcoef = vals[candpos] - restcoef;
12086 else
12087 newcoef = vals[candpos] - restcoef + gcd;
12088 }
12089
12090 /* done */
12091
12092 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12093 * another with the big coefficient was set to 1
12094 */
12095 if( hasrhs && SCIPisZero(scip, newcoef) )
12096 {
12097 notchangable = TRUE;
12098 }
12099 else if( SCIPisZero(scip, newcoef) )
12100 {
12101 /* delete old redundant coefficient */
12102 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12103 ++(*nchgcoefs);
12104 }
12105 else
12106 {
12107 /* replace old with new coefficient */
12108 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12109 ++(*nchgcoefs);
12110 }
12111 }
12112 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12113 {
12114 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12115 }
12116
12117 /* correct side and big coefficients */
12118 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12119 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12120 {
12121 if( haslhs )
12122 {
12123 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12124
12125 SCIP_CALL( chgLhs(scip, cons, newcoef) );
12126 ++(*nchgsides);
12127 }
12128 else
12129 {
12130 assert(hasrhs);
12131 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12132
12133 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12134 ++(*nchgsides);
12135 }
12136
12137 /* correct coefficients up front */
12138 for( w = offsetv; w >= 0; --w )
12139 {
12140 assert(vals[w] > 0);
12141
12142 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12143 }
12144 (*nchgcoefs) += (offsetv + 1);
12145 }
12146
12147 if( !notchangable )
12148 {
12149 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12150 assert(vars == consdata->vars);
12151 assert(vals == consdata->vals);
12152
12153 if( *infeasible )
12154 return SCIP_OKAY;
12155
12156 /* get new constraint data */
12157 nvars = consdata->nvars;
12158 assert(nvars >= 2);
12159
12161
12162 lhs = consdata->lhs;
12163 rhs = consdata->rhs;
12164 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12165 assert(!haslhs || !SCIPisNegative(scip, lhs));
12166 }
12167 }
12168 }
12169 }
12170
12171 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12172 /* no continuous variables are left over */
12173 if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12174 return SCIP_OKAY;
12175
12176 onlybin = TRUE;
12177 allcoefintegral = TRUE;
12178 /* check if all variables are of binary type */
12179 for( v = nvars - 1; v >= 0; --v )
12180 {
12181 if( !SCIPvarIsBinary(vars[v]) )
12182 onlybin = FALSE;
12183 if( !SCIPisIntegral(scip, vals[v]) )
12184 allcoefintegral = FALSE;
12185 }
12186
12187 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12188 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12189 *
12190 * @todo there are some steps missing ....
12191 */
12192 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12193 {
12194 SCIP_Real val;
12195 SCIP_Real newval;
12196 SCIP_Real frac = 0.0;
12197 SCIP_Bool found = FALSE;
12198
12199 if( hasrhs )
12200 {
12201 if( allcoefintegral )
12202 {
12203 /* replace old with new right hand side */
12204 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12205 ++(*nchgsides);
12206 }
12207 else
12208 {
12209 siderest = rhs - SCIPfloor(scip, rhs);
12210
12211 /* try to round down all non-integral coefficients */
12212 for( v = nvars - 1; v >= 0; --v )
12213 {
12214 val = vals[v];
12215
12216 /* add up all possible fractional parts */
12217 if( !SCIPisIntegral(scip, val) )
12218 {
12219 lb = SCIPvarGetLbGlobal(vars[v]);
12220 ub = SCIPvarGetUbGlobal(vars[v]);
12221
12222 /* at least one bound need to be at zero */
12223 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12224 return SCIP_OKAY;
12225
12226 /* swap bounds for 'standard' form */
12227 if( !SCIPisFeasZero(scip, lb) )
12228 {
12229 ub = lb;
12230 val *= -1;
12231 }
12232
12233 found = TRUE;
12234
12235 frac += (val - SCIPfloor(scip, val)) * ub;
12236
12237 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12238 *
12239 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12240 * x3, x4 set to 1 would be infeasible but feasible after flooring
12241 */
12242 if( SCIPisGT(scip, frac, siderest) )
12243 return SCIP_OKAY;
12244 }
12245 }
12246 assert(v == -1);
12247
12248 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12249
12250 /* round rhs and coefficients to integral values */
12251 if( found )
12252 {
12253 for( v = nvars - 1; v >= 0; --v )
12254 {
12255 val = vals[v];
12256
12257 /* add the whole fractional part */
12258 if( !SCIPisIntegral(scip, val) )
12259 {
12260 lb = SCIPvarGetLbGlobal(vars[v]);
12261
12262 if( SCIPisFeasZero(scip, lb) )
12263 newval = SCIPfloor(scip, val);
12264 else
12265 newval = SCIPceil(scip, val);
12266
12267 if( SCIPisZero(scip, newval) )
12268 {
12269 /* delete old redundant coefficient */
12270 SCIP_CALL( delCoefPos(scip, cons, v) );
12271 ++(*nchgcoefs);
12272 }
12273 else
12274 {
12275 /* replace old with new coefficient */
12276 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12277 ++(*nchgcoefs);
12278 }
12279 }
12280 }
12281 }
12282
12283 /* replace old with new right hand side */
12284 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12285 ++(*nchgsides);
12286 }
12287 }
12288 else
12289 {
12290 if( allcoefintegral )
12291 {
12292 /* replace old with new left hand side */
12293 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12294 ++(*nchgsides);
12295 }
12296 else
12297 {
12298 /* cannot floor left hand side to zero */
12299 if( SCIPisLT(scip, lhs, 1.0) )
12300 return SCIP_OKAY;
12301
12302 siderest = lhs - SCIPfloor(scip, lhs);
12303
12304 /* try to round down all non-integral coefficients */
12305 for( v = nvars - 1; v >= 0; --v )
12306 {
12307 val = vals[v];
12308
12309 /* add up all possible fractional parts */
12310 if( !SCIPisIntegral(scip, val) )
12311 {
12312 lb = SCIPvarGetLbGlobal(vars[v]);
12313 ub = SCIPvarGetUbGlobal(vars[v]);
12314
12315 /* at least one bound need to be at zero */
12316 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12317 return SCIP_OKAY;
12318
12319 /* swap bounds for 'standard' form */
12320 if( !SCIPisFeasZero(scip, lb) )
12321 {
12322 ub = lb;
12323 val *= -1;
12324 }
12325
12326 /* cannot floor to zero */
12327 if( SCIPisLT(scip, val, 1.0) )
12328 return SCIP_OKAY;
12329
12330 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12331 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12332 return SCIP_OKAY;
12333
12334 found = TRUE;
12335
12336 frac += (val - SCIPfloor(scip, val)) * ub;
12337
12338 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12339 * fractional parts of the variables, we cannot tighten the coefficients
12340 *
12341 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12342 * x2-x4 set to 1 would be feasible but not after flooring
12343 */
12344 if( SCIPisGE(scip, frac, 1 + siderest) )
12345 return SCIP_OKAY;
12346 }
12347 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12348 else
12349 return SCIP_OKAY;
12350 }
12351 assert(v == -1);
12352
12353 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12354
12355 /* round lhs and coefficients to integral values */
12356 if( found )
12357 {
12358 for( v = nvars - 1; v >= 0; --v )
12359 {
12360 val = vals[v];
12361
12362 /* add the whole fractional part */
12363 if( !SCIPisIntegral(scip, val) )
12364 {
12365 lb = SCIPvarGetLbGlobal(vars[v]);
12366
12367 if( SCIPisFeasZero(scip, lb) )
12368 newval = SCIPfloor(scip, val);
12369 else
12370 newval = SCIPceil(scip, val);
12371
12372 if( SCIPisZero(scip, newval) )
12373 {
12374 /* delete old redundant coefficient */
12375 SCIP_CALL( delCoefPos(scip, cons, v) );
12376 ++(*nchgcoefs);
12377 }
12378 else
12379 {
12380 /* replace old with new coefficient */
12381 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12382 ++(*nchgcoefs);
12383 }
12384 }
12385 }
12386 }
12387
12388 /* replace old with new left hand side */
12389 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12390 ++(*nchgsides);
12391 }
12392 }
12393
12394 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12395 assert(vars == consdata->vars);
12396 assert(vals == consdata->vals);
12397
12398 if( *infeasible )
12399 return SCIP_OKAY;
12400
12401 rhs = consdata->rhs;
12402 lhs = consdata->lhs;
12403
12404 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12405 assert(!haslhs || !SCIPisNegative(scip, lhs));
12406
12408
12409 nvars = consdata->nvars;
12410 if( nvars < 2 )
12411 return SCIP_OKAY;
12412
12413 allcoefintegral = TRUE;
12414#ifndef NDEBUG
12415 /* debug check if all coefficients are really integral */
12416 for( v = nvars - 1; v >= 0; --v )
12417 assert(SCIPisIntegral(scip, vals[v]));
12418#endif
12419 }
12420
12421 /* @todo following can also work on non integral coefficients, need more investigation */
12422 /* only check constraints with integral coefficients on all integral variables */
12423 if( !allcoefintegral )
12424 return SCIP_OKAY;
12425
12426 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12427 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12428 return SCIP_OKAY;
12429
12430 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12431 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12432 return SCIP_OKAY;
12433
12434 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12435 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12436 return SCIP_OKAY;
12437
12438 assert(nvars >= 2);
12439
12440 /* start gcd procedure for all variables */
12441 do
12442 {
12443 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12444 SCIPdebug( oldnchgsides = *nchgsides; )
12445
12446 /* stop if we have two coeffcients which are one in absolute value */
12447 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12448 return SCIP_OKAY;
12449
12450 gcd = -1;
12451
12452 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12453 * because coefficients of non-binary variables might have changed to zero */
12454 if( !onlybin )
12455 {
12456 foundbin = -1;
12457 onlybin = TRUE;
12458
12459 for( v = nvars - 1; v >= 0; --v )
12460 {
12461 assert(!SCIPisZero(scip, vals[v]));
12462 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12463
12464 if( SCIPvarIsBinary(vars[v]) )
12465 {
12466 if( foundbin == -1 )
12467 foundbin = v;
12468 continue;
12469 }
12470 else
12471 onlybin = FALSE;
12472
12473 absval = REALABS(vals[v]);
12474 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12475 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12476 */
12477 assert(SCIPisFeasIntegral(scip, absval));
12478
12479 if( gcd == -1 )
12480 {
12481 gcd = (SCIP_Longint)(absval + feastol);
12482 assert(gcd >= 1);
12483 }
12484 else
12485 {
12486 /* calculate greatest common divisor for all general variables */
12487 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12488 }
12489 if( gcd == 1 )
12490 break;
12491 }
12492 }
12493 else
12494 foundbin = nvars - 1;
12495
12496 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12497 if( gcd == 1 || foundbin == -1)
12498 return SCIP_OKAY;
12499
12500 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12501
12502 candpos = -1;
12503 candpos2 = -1;
12504
12505 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12506 * change the coefficient
12507 */
12508 for( v = foundbin; v >= 0; --v )
12509 {
12510 if( onlybin || SCIPvarIsBinary(vars[v]) )
12511 {
12512 absval = REALABS(vals[v]);
12513 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12514 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12515 */
12516 assert(SCIPisFeasIntegral(scip, absval));
12517
12518 oldgcd = gcd;
12519
12520 if( gcd == -1 )
12521 {
12522 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12523 assert(gcd >= 1);
12524 }
12525 else
12526 {
12527 /* calculate greatest common divisor for all general and binary variables */
12528 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12529 }
12530
12531 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12532 * can terminate
12533 */
12534 if( gcd == 1 )
12535 {
12536 /* found candidate */
12537 if( candpos == -1 )
12538 {
12539 gcd = oldgcd;
12540 candpos = v;
12541
12542 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12543 * the coefficient change
12544 */
12545 if( onlybin && v == foundbin - 1 )
12546 candpos2 = foundbin;
12547 }
12548 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12549 else
12550 {
12551 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12552 {
12553 assert(candpos2 == nvars - 1);
12554
12555 /* take new candidates */
12556 candpos = candpos2;
12557
12558 /* recalculate gcd from scratch */
12559 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12560 assert(gcd >= 1);
12561
12562 /* calculate greatest common divisor for all general and binary variables */
12563 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12564 if( gcd == 1 )
12565 return SCIP_OKAY;
12566 }
12567 else
12568 /* cannot determine a possible coefficient for reduction */
12569 return SCIP_OKAY;
12570 }
12571 }
12572 }
12573 }
12574 assert(gcd >= 2);
12575
12576 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12577 * further
12578 */
12579 assert(candpos >= 0 && candpos < nvars);
12580
12581 /* all variables and all coefficients are integral, so the side should be too */
12582 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12583
12584 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12585 * @see normalizeCons()
12586 */
12587 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12588 assert(!haslhs || !SCIPisNegative(scip, lhs));
12589
12590 /* determine the remainder of the side and the gcd */
12591 if( hasrhs )
12592 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12593 else
12594 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12595 assert(rest >= 0);
12596 assert(rest < gcd);
12597
12598 /* determine the remainder of the coefficient candidate and the gcd */
12599 if( vals[candpos] < 0 )
12600 {
12601 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12602 assert(restcoef <= -1);
12603 restcoef += gcd;
12604 }
12605 else
12606 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12607 assert(restcoef >= 1);
12608 assert(restcoef < gcd);
12609
12610 if( hasrhs )
12611 {
12612 if( rest > 0 )
12613 {
12614 /* replace old with new right hand side */
12615 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12616 ++(*nchgsides);
12617 }
12618
12619 /* calculate new coefficient */
12620 if( restcoef > rest )
12621 newcoef = vals[candpos] - restcoef + gcd;
12622 else
12623 newcoef = vals[candpos] - restcoef;
12624 }
12625 else
12626 {
12627 if( rest > 0 )
12628 {
12629 /* replace old with new left hand side */
12630 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12631 ++(*nchgsides);
12632 }
12633
12634 /* calculate new coefficient */
12635 if( rest == 0 || restcoef < rest )
12636 newcoef = vals[candpos] - restcoef;
12637 else
12638 newcoef = vals[candpos] - restcoef + gcd;
12639 }
12640 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12641
12642 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));
12643
12644 if( SCIPisZero(scip, newcoef) )
12645 {
12646 /* delete redundant coefficient */
12647 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12648 }
12649 else
12650 {
12651 /* replace old with new coefficient */
12652 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12653 }
12654 ++(*nchgcoefs);
12655
12656 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12657 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12658 assert(vars == consdata->vars);
12659 assert(vals == consdata->vals);
12660
12661 if( *infeasible )
12662 return SCIP_OKAY;
12663
12665
12666 rhs = consdata->rhs;
12667 lhs = consdata->lhs;
12668 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12669 assert(!haslhs || !SCIPisNegative(scip, lhs));
12670
12671 nvars = consdata->nvars;
12672
12673 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));
12674 }
12675 while( nvars >= 2 );
12676
12677 return SCIP_OKAY;
12678}
12679
12680
12681/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12682 * cons0 := a * cons0 + b * cons1,
12683 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12684 * for numerical stability, we will only accept integral a and b;
12685 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12686 * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12687 */
12688static
12690 SCIP* scip, /**< SCIP data structure */
12691 SCIP_CONS* cons0, /**< (in)equality to modify */
12692 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12693 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12694 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12695 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12696 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12697 int nvarscommon, /**< number of variables, that appear in both constraints */
12698 int commonidxweight, /**< variable weight sum of common variables */
12699 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12700 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12701 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12702 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12703 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12704 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12705 )
12706{
12707 SCIP_CONSDATA* consdata0;
12708 SCIP_CONSDATA* consdata1;
12709 SCIP_Real a;
12710 SCIP_Real b;
12711 SCIP_Real aggrcoef;
12712 SCIP_Real scalarsum;
12713 SCIP_Real bestscalarsum;
12714 SCIP_Bool betterscalarsum;
12715 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12716 int varweight;
12717 int nvars;
12718 int bestvarweight;
12719 int bestnvars;
12720 int bestv;
12721 int v;
12722 int i;
12723
12724 assert(scip != NULL);
12725 assert(cons0 != NULL);
12726 assert(cons1 != NULL);
12727 assert(commonidx0 != NULL);
12728 assert(commonidx1 != NULL);
12729 assert(diffidx0minus1 != NULL);
12730 assert(diffidx1minus0 != NULL);
12731 assert(nvarscommon >= 1);
12732 assert(commonidxweight >= nvarscommon);
12733 assert(nchgcoefs != NULL);
12734 assert(aggregated != NULL);
12735
12736 assert(SCIPconsIsActive(cons0));
12737 assert(SCIPconsIsActive(cons1));
12738
12739 *infeasible = FALSE;
12740
12741 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12742
12743 /* cons0 is an (in)equality */
12744 consdata0 = SCIPconsGetData(cons0);
12745 assert(consdata0 != NULL);
12746 assert(consdata0->nvars >= 1);
12747 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12748 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12749
12750 /* cons1 is an equality */
12751 consdata1 = SCIPconsGetData(cons1);
12752 assert(consdata1 != NULL);
12753 assert(consdata1->nvars >= 1);
12754 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12755 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12756
12757 *aggregated = FALSE;
12758
12759 /* search for the best common variable such that
12760 * val1[var] * consdata0 - val0[var] * consdata1
12761 * has least weighted number of variables
12762 */
12763 bestvarweight = commonidxweight + diffidx0minus1weight;
12764 bestnvars = consdata0->nvars;
12765 bestv = -1;
12766 bestscalarsum = 0.0;
12767 commonvarlindependent = TRUE;
12768 for( v = 0; v < nvarscommon; ++v )
12769 {
12770 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12771 a = consdata1->vals[commonidx1[v]];
12772 b = -consdata0->vals[commonidx0[v]];
12773
12774 /* only try aggregation, if coefficients are integral (numerical stability) */
12776 {
12777 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12778 varweight = diffidx0minus1weight + diffidx1minus0weight;
12779 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12780 scalarsum = REALABS(a) + REALABS(b);
12781 betterscalarsum = (scalarsum < bestscalarsum);
12782 for( i = 0; i < nvarscommon
12783 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12784 {
12785 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12786 if( !SCIPisZero(scip, aggrcoef) )
12787 {
12788 varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12789 nvars++;
12790 }
12791 }
12792 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12793 {
12794 bestv = v;
12795 bestvarweight = varweight;
12796 bestnvars = nvars;
12797 bestscalarsum = scalarsum;
12798 }
12799 }
12800
12801 /* update commonvarlindependent flag, if still TRUE:
12802 * 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
12803 */
12804 if( commonvarlindependent && v > 0 )
12805 commonvarlindependent = SCIPisEQ(scip,
12806 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12807 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12808 }
12809
12810 /* if better aggregation was found, create new constraint and delete old one */
12811 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12812 {
12813 SCIP_CONS* newcons;
12814 SCIP_CONSDATA* newconsdata;
12815 SCIP_VAR** newvars;
12816 SCIP_Real* newvals;
12817 SCIP_Real newlhs;
12818 SCIP_Real newrhs;
12819 int newnvars;
12820
12821 if( bestv != -1 )
12822 {
12823 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12824 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12825 {
12826 a = consdata1->vals[commonidx1[bestv]];
12827 b = -consdata0->vals[commonidx0[bestv]];
12828 }
12829 else
12830 {
12831 a = -consdata1->vals[commonidx1[bestv]];
12832 b = consdata0->vals[commonidx0[bestv]];
12833 }
12834 assert(SCIPisIntegral(scip, a));
12835 assert(SCIPisPositive(scip, a));
12836 assert(SCIPisIntegral(scip, b));
12837 assert(!SCIPisZero(scip, b));
12838 }
12839 else
12840 {
12841 assert(commonvarlindependent);
12842 if( consdata1->vals[commonidx1[0]] > 0.0 )
12843 {
12844 a = consdata1->vals[commonidx1[0]];
12845 b = -consdata0->vals[commonidx0[0]];
12846 }
12847 else
12848 {
12849 a = -consdata1->vals[commonidx1[0]];
12850 b = consdata0->vals[commonidx0[0]];
12851 }
12852 assert(SCIPisPositive(scip, a));
12853 assert(!SCIPisZero(scip, b));
12854
12855 /* if a/b is integral, then we can easily choose integer multipliers */
12856 if( SCIPisIntegral(scip, a/b) )
12857 {
12858 if( a/b > 0 )
12859 {
12860 a /= b;
12861 b = 1.0;
12862 }
12863 else
12864 {
12865 a /= -b;
12866 b = -1.0;
12867 }
12868 }
12869
12870 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12871 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12872 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12873 }
12874
12875 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12876 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12877 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12878 SCIPdebugPrintCons(scip, cons0, NULL);
12879 SCIPdebugPrintCons(scip, cons1, NULL);
12880
12881 /* get temporary memory for creating the new linear constraint */
12882 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12883 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12884
12885 /* calculate the common coefficients, if we have not recognized linear dependency */
12886 newnvars = 0;
12887 if( !commonvarlindependent )
12888 {
12889 for( i = 0; i < nvarscommon; ++i )
12890 {
12891 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12892 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12893
12894 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12895 if( !SCIPisZero(scip, aggrcoef) )
12896 {
12897 assert(newnvars < bestnvars);
12898 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12899 newvals[newnvars] = aggrcoef;
12900 newnvars++;
12901 }
12902 }
12903 }
12904 else
12905 {
12906 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12907#ifndef NDEBUG
12908 for( i = 0; i < nvarscommon; ++i )
12909 {
12910 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12911 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12912
12913 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12914 assert(SCIPisZero(scip, aggrcoef));
12915 }
12916#endif
12917 }
12918
12919 /* calculate the coefficients appearing in cons0 but not in cons1 */
12920 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12921 {
12922 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12923
12924 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12925 assert(!SCIPisZero(scip, aggrcoef));
12926 assert(newnvars < bestnvars);
12927 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12928 newvals[newnvars] = aggrcoef;
12929 newnvars++;
12930 }
12931
12932 /* calculate the coefficients appearing in cons1 but not in cons0 */
12933 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12934 {
12935 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12936
12937 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12938 assert(!SCIPisZero(scip, aggrcoef));
12939 assert(newnvars < bestnvars);
12940 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12941 newvals[newnvars] = aggrcoef;
12942 newnvars++;
12943 }
12944 assert(newnvars == bestnvars);
12945
12946 /* calculate the new left and right hand side of the (in)equality */
12947 assert(!SCIPisInfinity(scip, -consdata1->lhs));
12948 assert(!SCIPisInfinity(scip, consdata1->rhs));
12949 if( SCIPisInfinity(scip, -consdata0->lhs) )
12950 newlhs = -SCIPinfinity(scip);
12951 else
12952 newlhs = a * consdata0->lhs + b * consdata1->lhs;
12953 if( SCIPisInfinity(scip, consdata0->rhs) )
12954 newrhs = SCIPinfinity(scip);
12955 else
12956 newrhs = a * consdata0->rhs + b * consdata1->rhs;
12957
12958 /* create the new linear constraint */
12959 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12964
12965 newconsdata = SCIPconsGetData(newcons);
12966 assert(newconsdata != NULL);
12967
12968 /* copy the upgraded flag from the old cons0 to the new constraint */
12969 newconsdata->upgraded = consdata0->upgraded;
12970
12971 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12972
12973 if( *infeasible )
12974 goto TERMINATE;
12975
12976 /* check, if we really want to use the new constraint instead of the old one:
12977 * use the new one, if the maximum norm doesn't grow too much
12978 */
12979 if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12980 {
12981 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12982 SCIPdebugPrintCons(scip, newcons, NULL);
12983
12984 /* update the statistics: we changed all coefficients */
12985 if( !consdata0->upgraded )
12986 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12987 *aggregated = TRUE;
12988
12989 /* delete the old constraint, and add the new linear constraint to the problem */
12990 SCIP_CALL( SCIPdelCons(scip, cons0) );
12991 SCIP_CALL( SCIPaddCons(scip, newcons) );
12992 }
12993
12994 TERMINATE:
12995 /* release the new constraint */
12996 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12997
12998 /* free temporary memory */
12999 SCIPfreeBufferArray(scip, &newvals);
13000 SCIPfreeBufferArray(scip, &newvars);
13001 }
13002
13003 return SCIP_OKAY;
13004}
13005
13006/** gets the key of the given element */
13007static
13008SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
13009{ /*lint --e{715}*/
13010 /* the key is the element itself */
13011 return elem;
13012}
13013
13014/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13015 * coefficients are either equal or negated
13016 */
13017static
13018SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
13019{
13020 SCIP* scip;
13021 SCIP_CONSDATA* consdata1;
13022 SCIP_CONSDATA* consdata2;
13023 SCIP_Real minscale;
13024 SCIP_Real maxscale;
13025 int i;
13026
13027 assert(key1 != NULL);
13028 assert(key2 != NULL);
13029 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13030 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13031 assert(consdata1->indexsorted);
13032 assert(consdata2->indexsorted);
13033
13034 scip = (SCIP*)userptr;
13035 assert(scip != NULL);
13036
13037 /* if it is the same constraint we dont need to check anything */
13038 if( key1 == key2 )
13039 return TRUE;
13040
13041 /* checks trivial case */
13042 if( consdata1->nvars != consdata2->nvars )
13043 return FALSE;
13044
13045 /* tests if variables are equal */
13046 for( i = 0; i < consdata1->nvars; ++i )
13047 {
13048 if( consdata1->vars[i] != consdata2->vars[i] )
13049 {
13050 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13051 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13052 return FALSE;
13053 }
13054 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13055 }
13056
13057 /* order by maxabsval */
13058 if( consdataGetMaxAbsval(consdata1) > consdataGetMaxAbsval(consdata2) )
13059 SCIPswapPointers((void**)&consdata1, (void**)&consdata2);
13060
13061 /* initialize extremal scales */
13062 minscale = SCIPinfinity(scip);
13063 maxscale = -SCIPinfinity(scip);
13064
13065 /* test if coefficient scales are equal */
13066 for( i = 0; i < consdata1->nvars; ++i )
13067 {
13068 SCIP_Real scale = consdata2->vals[i] / consdata1->vals[i];
13069
13070 if( minscale > scale )
13071 {
13072 minscale = scale;
13073
13074 if( SCIPisLT(scip, minscale, maxscale) )
13075 return FALSE;
13076 }
13077
13078 if( maxscale < scale )
13079 {
13080 maxscale = scale;
13081
13082 if( SCIPisLT(scip, minscale, maxscale) )
13083 return FALSE;
13084 }
13085 }
13086
13087 return TRUE;
13088}
13089
13090/** returns the hash value of the key */
13091static
13092SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13093{
13094 SCIP_CONSDATA* consdata;
13095 int minidx;
13096 int mididx;
13097 int maxidx;
13098#ifndef NDEBUG
13099 SCIP* scip;
13100
13101 scip = (SCIP*)userptr;
13102 assert(scip != NULL);
13103#endif
13104
13105 assert(key != NULL);
13106 consdata = SCIPconsGetData((SCIP_CONS*)key);
13107 assert(consdata != NULL);
13108 assert(consdata->nvars > 0);
13109
13110 assert(consdata->indexsorted);
13111
13112 minidx = SCIPvarGetIndex(consdata->vars[0]);
13113 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13114 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13115
13116 /* using only the variable indices as hash, since the values are compared by epsilon */
13117 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
13118}
13119
13120/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13121 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13122 */
13123static
13125 SCIP_CONS* cons /**< linear constraint */
13126 )
13127{
13128 SCIP_CONSDATA* consdata;
13129
13130 assert(cons != NULL);
13131
13132 consdata = SCIPconsGetData(cons);
13133 assert(consdata != NULL);
13134
13135 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13136}
13137
13138/** updates the hashtable such that out of all constraints in the hashtable that are detected
13139 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13140 * and all others are removed from the hashtable and stored in the given array
13141 */
13142static
13144 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13145 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13146 * upon return will contain the constraint that should be kept */
13147 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13148 * these constraints where removed from the hashtable */
13149 int* nparallelconss /**< pointer to return number of parallel constraints */
13150 )
13151{
13152 SCIP_CONS* parallelcons;
13153 unsigned int querykey;
13154
13155 *nparallelconss = 0;
13156 querykey = getParallelConsKey(*querycons);
13157
13158 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13159 {
13160 unsigned int conskey = getParallelConsKey(parallelcons);
13161
13162 if( conskey < querykey )
13163 {
13164 parallelconss[(*nparallelconss)++] = *querycons;
13165 *querycons = parallelcons;
13166 querykey = conskey;
13167 }
13168 else
13169 {
13170 parallelconss[(*nparallelconss)++] = parallelcons;
13171 }
13172
13173 /* if the constraint that just came out of the hash table is the one that is kept,
13174 * we do not need to look into the hashtable again, since the invariant is that
13175 * in the hashtable only pair-wise non-parallel constraints are contained.
13176 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13177 * could be contained due to non-transitivity of the equality comparison.
13178 * Also we can return immediately, since parallelcons is already contained in the
13179 * hashtable and we do not need to remove and reinsert it.
13180 */
13181 if( *querycons == parallelcons )
13182 return SCIP_OKAY;
13183
13184 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13185 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13186 }
13187
13188 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13189 * comnpares equal to querycons at this point
13190 */
13191#ifndef NDEBUG
13192 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13193#else
13194 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13195#endif
13196
13197 return SCIP_OKAY;
13198}
13199
13200/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13201 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13202 */
13203static
13205 SCIP* scip, /**< SCIP data structure */
13206 BMS_BLKMEM* blkmem, /**< block memory */
13207 SCIP_CONS** conss, /**< constraint set */
13208 int nconss, /**< number of constraints in constraint set */
13209 int* firstchange, /**< pointer to store first changed constraint */
13210 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13211 int* ndelconss, /**< pointer to count number of deleted constraints */
13212 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13213 )
13214{
13215 SCIP_HASHTABLE* hashtable;
13216 SCIP_CONS** parallelconss;
13217 int nparallelconss;
13218 int hashtablesize;
13219 int c;
13220
13221 assert(scip != NULL);
13222 assert(blkmem != NULL);
13223 assert(conss != NULL);
13224 assert(firstchange != NULL);
13225 assert(cutoff != NULL);
13226 assert(ndelconss != NULL);
13227 assert(nchgsides != NULL);
13228
13229 /* create a hash table for the constraint set */
13230 hashtablesize = nconss;
13231 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13232 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13233
13234 SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13235
13236 /* check all constraints in the given set for redundancy */
13237 for( c = 0; c < nconss; ++c )
13238 {
13239 SCIP_CONS* cons0;
13240 SCIP_CONSDATA* consdata0;
13241
13242 cons0 = conss[c];
13243
13244 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13245 continue;
13246
13247 /* do not check for parallel constraints if they should not be upgraded */
13248 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13249 continue;
13250
13251 /* check for interuption */
13252 if( c % 1000 == 0 && SCIPisStopped(scip) )
13253 break;
13254
13255 /* sorts the constraint */
13256 consdata0 = SCIPconsGetData(cons0);
13257 assert(consdata0 != NULL);
13258 SCIP_CALL( consdataSort(scip, consdata0) );
13259 assert(consdata0->indexsorted);
13260
13261 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13262 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13263 * first variable is positive
13264 * Also inserts cons0 into the hashtable.
13265 */
13266 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13267
13268 if( nparallelconss != 0 )
13269 {
13270 SCIP_Real lhs;
13271 SCIP_Real rhs;
13272
13273 int i;
13274
13275 /* cons0 may have been changed in retrieveParallelConstraints() */
13276 consdata0 = SCIPconsGetData(cons0);
13277
13278 lhs = consdata0->lhs;
13279 rhs = consdata0->rhs;
13280
13281 for( i = 0; i < nparallelconss; ++i )
13282 {
13283 SCIP_CONS* consdel;
13284 SCIP_CONSDATA* consdatadel;
13285 SCIP_Real scale;
13286
13287 consdel = parallelconss[i];
13288 consdatadel = SCIPconsGetData(consdel);
13289
13290 /* do not delete constraint if it should not be upgraded */
13291 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13292 continue;
13293
13294 assert(SCIPconsIsActive(consdel));
13295 assert(!SCIPconsIsModifiable(consdel));
13296
13297 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13298 * delete old constraints afterwards
13299 */
13300 assert(consdatadel != NULL);
13301 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13302
13303 assert(consdatadel->indexsorted);
13304 assert(consdata0->vars[0] == consdatadel->vars[0]);
13305
13306 scale = consdata0->vals[0] / consdatadel->vals[0];
13307 assert(scale != 0.0);
13308
13309 /* in debug mode, check that all coefficients are equal with respect to epsilon
13310 * if the constraints are in equilibrium scale
13311 */
13312#ifndef NDEBUG
13313 {
13314 assert(consdata0->validmaxabsval);
13315 assert(consdatadel->validmaxabsval);
13316 int k;
13317 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13318 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13319
13320 for( k = 0; k < consdata0->nvars; ++k )
13321 {
13322 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13323 }
13324 }
13325#endif
13326
13327 if( scale > 0.0 )
13328 {
13329 /* the coefficients of both constraints are parallel with a positive scale */
13330 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13331 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13332 SCIPdebugPrintCons(scip, cons0, NULL);
13333 SCIPdebugPrintCons(scip, consdel, NULL);
13334
13335 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13336 lhs = MAX(scale * consdatadel->lhs, lhs);
13337
13338 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13339 rhs = MIN(scale * consdatadel->rhs, rhs);
13340 }
13341 else
13342 {
13343 /* the coefficients of both rows are negations */
13344 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13345 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13346 SCIPdebugPrintCons(scip, cons0, NULL);
13347 SCIPdebugPrintCons(scip, consdel, NULL);
13348
13349 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13350 lhs = MAX(scale * consdatadel->rhs, lhs);
13351
13352 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13353 rhs = MIN(scale * consdatadel->lhs, rhs);
13354 }
13355
13356 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13357 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13358
13359 /* delete consdel */
13360 assert( ! consdata0->upgraded || consdatadel->upgraded );
13361 SCIP_CALL( SCIPdelCons(scip, consdel) );
13362 if( !consdatadel->upgraded )
13363 (*ndelconss)++;
13364 }
13365
13366 if( SCIPisFeasLT(scip, rhs, lhs) )
13367 {
13368 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13369 *cutoff = TRUE;
13370 break;
13371 }
13372
13373 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13374 if( lhs > rhs )
13375 {
13376 rhs = (lhs + rhs)/2;
13377 lhs = rhs;
13378 }
13379
13380 /* update lhs and rhs of cons0 */
13381 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13382 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13383
13384 /* update the first changed constraint to begin the next aggregation round with */
13385 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13386 *firstchange = SCIPconsGetPos(cons0);
13387
13388 assert(SCIPconsIsActive(cons0));
13389 }
13390 }
13391#ifdef SCIP_MORE_DEBUG
13392 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13394#endif
13395
13396 SCIPfreeBufferArray(scip, &parallelconss);
13397
13398 /* free hash table */
13399 SCIPhashtableFree(&hashtable);
13400
13401 return SCIP_OKAY;
13402}
13403
13404/** compares constraint with all prior constraints for possible redundancy or aggregation,
13405 * and removes or changes constraint accordingly
13406 */
13407static
13409 SCIP* scip, /**< SCIP data structure */
13410 SCIP_CONS** conss, /**< constraint set */
13411 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13412 int chkind, /**< index of constraint to check against all prior indices upto startind */
13413 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13414 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13415 int* ndelconss, /**< pointer to count number of deleted constraints */
13416 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13417 int* nchgcoefs /**< pointer to count number of changed coefficients */
13418 )
13419{
13420 SCIP_CONS* cons0;
13421 SCIP_CONSDATA* consdata0;
13422 int* commonidx0;
13423 int* commonidx1;
13424 int* diffidx0minus1;
13425 int* diffidx1minus0;
13426 uint64_t possignature0;
13427 uint64_t negsignature0;
13428 SCIP_Bool cons0changed;
13429 SCIP_Bool cons0isequality;
13430 int diffidx1minus0size;
13431 int c;
13432 SCIP_Real cons0lhs;
13433 SCIP_Real cons0rhs;
13434 SCIP_Bool cons0upgraded;
13435
13436 assert(scip != NULL);
13437 assert(conss != NULL);
13438 assert(firstchange <= chkind);
13439 assert(cutoff != NULL);
13440 assert(ndelconss != NULL);
13441 assert(nchgsides != NULL);
13442 assert(nchgcoefs != NULL);
13443
13444 /* get the constraint to be checked against all prior constraints */
13445 cons0 = conss[chkind];
13446 assert(cons0 != NULL);
13447 assert(SCIPconsIsActive(cons0));
13448 assert(!SCIPconsIsModifiable(cons0));
13449
13450 consdata0 = SCIPconsGetData(cons0);
13451 assert(consdata0 != NULL);
13452 assert(consdata0->nvars >= 1);
13453 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13454
13455 /* sort the constraint */
13456 SCIP_CALL( consdataSort(scip, consdata0) );
13457
13458 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13459 consdataCalcSignatures(consdata0);
13460 possignature0 = consdata0->possignature;
13461 negsignature0 = consdata0->negsignature;
13462
13463 /* get temporary memory for indices of common variables */
13464 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13465 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13466 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13467 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13468 diffidx1minus0size = consdata0->nvars;
13469
13470 cons0lhs = consdata0->lhs;
13471 cons0rhs = consdata0->rhs;
13472 cons0upgraded = consdata0->upgraded;
13473
13474 /* check constraint against all prior constraints */
13475 cons0changed = consdata0->changed;
13476 consdata0->changed = FALSE;
13477 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13478 {
13479 SCIP_CONS* cons1;
13480 SCIP_CONSDATA* consdata1;
13481 uint64_t possignature1;
13482 uint64_t negsignature1;
13483 SCIP_Bool cons0dominateslhs;
13484 SCIP_Bool cons1dominateslhs;
13485 SCIP_Bool cons0dominatesrhs;
13486 SCIP_Bool cons1dominatesrhs;
13487 SCIP_Bool cons1isequality;
13488 SCIP_Bool coefsequal;
13489 SCIP_Bool coefsnegated;
13490 SCIP_Bool tryaggregation;
13491 int nvarscommon;
13492 int nvars0minus1;
13493 int nvars1minus0;
13494 int commonidxweight;
13495 int diffidx0minus1weight;
13496 int diffidx1minus0weight;
13497 int v0;
13498 int v1;
13499
13500 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13501 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13502 assert(cons0upgraded == consdata0->upgraded);
13503
13504 cons1 = conss[c];
13505
13506 /* cons1 has become inactive during presolving of constraint pairs */
13507 if( cons1 == NULL )
13508 continue;
13509
13510 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13511 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13512
13513 consdata1 = SCIPconsGetData(cons1);
13514 assert(consdata1 != NULL);
13515
13516 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13517 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13518 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13519
13520 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13521 if( !cons0changed && !consdata1->changed )
13522 continue;
13523
13524 /* if both constraints are already upgraded, skip the pair;
13525 * because changes on these constraints cannot be applied to the instance anymore */
13526 if( cons0upgraded && consdata1->upgraded )
13527 continue;
13528
13529 assert(consdata1->nvars >= 1);
13530
13531 /* sort the constraint */
13532 SCIP_CALL( consdataSort(scip, consdata1) );
13533
13534 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13535 consdataCalcSignatures(consdata1);
13536 possignature1 = consdata1->possignature;
13537 negsignature1 = consdata1->negsignature;
13538
13539 /* the signatures give a quick test to check for domination and equality of coefficients */
13540 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13541 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13542 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13543 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13544 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13545 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13546 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13547 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13548 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13549 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13550 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13551 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13552 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13553 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13554 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13555 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13556 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13557 && !coefsequal && !coefsnegated && !tryaggregation )
13558 continue;
13559
13560 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13561 if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13562 {
13563 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13564 diffidx1minus0size = consdata1->nvars;
13565 }
13566
13567 /* check consdata0 against consdata1:
13568 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13569 * consdata0 dominates consdata1 w.r.t. left hand side
13570 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13571 * consdata0 dominates consdata1 w.r.t. right hand side
13572 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13573 * ranged row (or equality)
13574 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13575 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13576 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13577 * number of continuous and integer variables are preferred:
13578 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13579 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13580 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13581 * to be positive to not switch the sense of the (in)equality cons0
13582 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13583 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13584 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13585 * to be positive to not switch the sense of the (in)equality cons1
13586 */
13587
13588 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13589 nvarscommon = 0;
13590 commonidxweight = 0;
13591 nvars0minus1 = 0;
13592 diffidx0minus1weight = 0;
13593 nvars1minus0 = 0;
13594 diffidx1minus0weight = 0;
13595 v0 = 0;
13596 v1 = 0;
13597 while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13598 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13599 || coefsequal || coefsnegated || tryaggregation) )
13600 {
13601 SCIP_VAR* var;
13602 SCIP_Real val0;
13603 SCIP_Real val1;
13604 int varcmp;
13605
13606 /* test, if variable appears in only one or in both constraints */
13607 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13608 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13609 else if( v0 < consdata0->nvars )
13610 varcmp = -1;
13611 else
13612 varcmp = +1;
13613
13614 switch( varcmp )
13615 {
13616 case -1:
13617 /* variable doesn't appear in consdata1 */
13618 var = consdata0->vars[v0];
13619 val0 = consdata0->vals[v0];
13620 val1 = 0.0;
13621 if( tryaggregation )
13622 {
13623 diffidx0minus1[nvars0minus1] = v0;
13624 nvars0minus1++;
13625 diffidx0minus1weight += getVarWeight(var);
13626 }
13627 v0++;
13628 coefsequal = FALSE;
13629 coefsnegated = FALSE;
13630 break;
13631
13632 case +1:
13633 /* variable doesn't appear in consdata0 */
13634 var = consdata1->vars[v1];
13635 val0 = 0.0;
13636 val1 = consdata1->vals[v1];
13637 if( tryaggregation )
13638 {
13639 diffidx1minus0[nvars1minus0] = v1;
13640 nvars1minus0++;
13641 diffidx1minus0weight += getVarWeight(var);
13642 }
13643 v1++;
13644 coefsequal = FALSE;
13645 coefsnegated = FALSE;
13646 break;
13647
13648 case 0:
13649 /* variable appears in both constraints */
13650 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13651 var = consdata0->vars[v0];
13652 val0 = consdata0->vals[v0];
13653 val1 = consdata1->vals[v1];
13654 if( tryaggregation )
13655 {
13656 commonidx0[nvarscommon] = v0;
13657 commonidx1[nvarscommon] = v1;
13658 nvarscommon++;
13659 commonidxweight += getVarWeight(var);
13660 }
13661 v0++;
13662 v1++;
13663 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13664 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13665 break;
13666
13667 default:
13668 SCIPerrorMessage("invalid comparison result\n");
13669 SCIPABORT();
13670 var = NULL;
13671 val0 = 0.0;
13672 val1 = 0.0;
13673 }
13674 assert(var != NULL);
13675
13676 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13677 if( SCIPisGT(scip, val0, val1) )
13678 {
13680 {
13681 cons0dominatesrhs = FALSE;
13682 cons1dominateslhs = FALSE;
13683 }
13685 {
13686 cons0dominateslhs = FALSE;
13687 cons1dominatesrhs = FALSE;
13688 }
13689 }
13690 else if( SCIPisLT(scip, val0, val1) )
13691 {
13693 {
13694 cons0dominateslhs = FALSE;
13695 cons1dominatesrhs = FALSE;
13696 }
13698 {
13699 cons0dominatesrhs = FALSE;
13700 cons1dominateslhs = FALSE;
13701 }
13702 }
13703 }
13704
13705 /* check for disaggregated ranged rows */
13706 if( coefsequal || coefsnegated )
13707 {
13708 SCIP_CONS* consstay;
13709 SCIP_CONS* consdel;
13710#ifndef NDEBUG
13711 SCIP_CONSDATA* consdatastay;
13712#endif
13713 SCIP_CONSDATA* consdatadel;
13714 SCIP_Real lhs;
13715 SCIP_Real rhs;
13716 int consinddel;
13717
13718 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13719 * best left and right hand sides; delete the old constraints afterwards
13720 */
13721 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13722 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13723 SCIPdebugPrintCons(scip, cons0, NULL);
13724 SCIPdebugPrintCons(scip, cons1, NULL);
13725
13726 if( coefsequal )
13727 {
13728 /* the coefficients of both rows are equal */
13729 lhs = MAX(consdata0->lhs, consdata1->lhs);
13730 rhs = MIN(consdata0->rhs, consdata1->rhs);
13731 }
13732 else
13733 {
13734 /* the coefficients of both rows are negations */
13735 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13736 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13737 }
13738 if( SCIPisFeasLT(scip, rhs, lhs) )
13739 {
13740 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13741 *cutoff = TRUE;
13742 break;
13743 }
13744
13745 /* check which constraint has to stay;
13746 * changes applied to an upgraded constraint will not be considered in the instance */
13747 if( consdata0->upgraded )
13748 {
13749 assert(!consdata1->upgraded);
13750 consstay = cons1;
13751#ifndef NDEBUG
13752 consdatastay = consdata1;
13753#endif
13754
13755 consdel = cons0;
13756 consdatadel = consdata0;
13757 consinddel = chkind;
13758 }
13759 else
13760 {
13761 consstay = cons0;
13762#ifndef NDEBUG
13763 consdatastay = consdata0;
13764#endif
13765
13766 consdel = cons1;
13767 consdatadel = consdata1;
13768 consinddel = c;
13769 }
13770
13771 /* update the sides of consstay */
13772 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13773 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13774 if( !consdata0->upgraded )
13775 {
13776 assert(consstay == cons0);
13777 cons0lhs = consdata0->lhs;
13778 cons0rhs = consdata0->rhs;
13779 }
13780
13781 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13782 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13783
13784 assert( !consdatastay->upgraded );
13785 /* delete consdel */
13786 SCIP_CALL( SCIPdelCons(scip, consdel) );
13787 conss[consinddel] = NULL;
13788 if( !consdatadel->upgraded )
13789 (*ndelconss)++;
13790 continue;
13791 }
13792
13793 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13794 * redundant
13795 */
13796 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13797 {
13798 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13799 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13800 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13801 SCIPdebugPrintCons(scip, cons0, NULL);
13802 SCIPdebugPrintCons(scip, cons1, NULL);
13803
13804 /* check for infeasibility */
13805 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13806 {
13807 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13808 *cutoff = TRUE;
13809 break;
13810 }
13811
13812 /* remove redundant left hand side */
13813 if( !SCIPisInfinity(scip, -consdata0->lhs) )
13814 {
13815 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13816 cons0lhs = consdata0->lhs;
13817 cons0isequality = FALSE;
13818 if( !consdata0->upgraded )
13819 {
13820 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13821 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13822
13823 (*nchgsides)++;
13824 }
13825 }
13826 }
13827 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13828 {
13829 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13830 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13831 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13832 SCIPdebugPrintCons(scip, cons1, NULL);
13833 SCIPdebugPrintCons(scip, cons0, NULL);
13834
13835 /* check for infeasibility */
13836 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13837 {
13838 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13839 *cutoff = TRUE;
13840 break;
13841 }
13842
13843 /* remove redundant left hand side */
13844 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13845 {
13846 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13847 cons1isequality = FALSE;
13848 if( !consdata1->upgraded )
13849 {
13850 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13851 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13852
13853 (*nchgsides)++;
13854 }
13855 }
13856 }
13857 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13858 {
13859 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13860 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13861 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13862 SCIPdebugPrintCons(scip, cons0, NULL);
13863 SCIPdebugPrintCons(scip, cons1, NULL);
13864
13865 /* check for infeasibility */
13866 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13867 {
13868 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13869 *cutoff = TRUE;
13870 break;
13871 }
13872
13873 /* remove redundant right hand side */
13874 if( !SCIPisInfinity(scip, consdata0->rhs) )
13875 {
13876 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13877 cons0rhs = consdata0->rhs;
13878 cons0isequality = FALSE;
13879 if( !consdata0->upgraded )
13880 {
13881 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13882 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13883
13884 (*nchgsides)++;
13885 }
13886 }
13887 }
13888 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13889 {
13890 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13891 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13892 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13893 SCIPdebugPrintCons(scip, cons1, NULL);
13894 SCIPdebugPrintCons(scip, cons0, NULL);
13895
13896 /* check for infeasibility */
13897 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13898 {
13899 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13900 *cutoff = TRUE;
13901 break;
13902 }
13903
13904 /* remove redundant right hand side */
13905 if( !SCIPisInfinity(scip, consdata1->rhs) )
13906 {
13907 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13908 cons1isequality = FALSE;
13909 if( !consdata1->upgraded )
13910 {
13911 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13912 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13913
13914 (*nchgsides)++;
13915 }
13916 }
13917 }
13918
13919 /* check for now redundant constraints */
13920 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13921 {
13922 /* consdata0 became redundant */
13923 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13924 SCIP_CALL( SCIPdelCons(scip, cons0) );
13925 conss[chkind] = NULL;
13926 if( !consdata0->upgraded )
13927 {
13928 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13929 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13930
13931 (*ndelconss)++;
13932 }
13933 continue;
13934 }
13935 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13936 {
13937 /* consdata1 became redundant */
13938 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13939 SCIP_CALL( SCIPdelCons(scip, cons1) );
13940 conss[c] = NULL;
13941 if( !consdata1->upgraded )
13942 {
13943 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13944 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13945
13946 (*ndelconss)++;
13947 }
13948 continue;
13949 }
13950
13951 /* check, if we want to aggregate an (in)equality with an equality:
13952 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13953 */
13954 if( tryaggregation )
13955 {
13956 SCIP_Bool aggregated;
13957
13958 assert(consdata0->nvars == nvarscommon + nvars0minus1);
13959 assert(consdata1->nvars == nvarscommon + nvars1minus0);
13960
13961 aggregated = FALSE;
13962 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13963 {
13964 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13965 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13966 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13967 nchgcoefs, &aggregated, cutoff) );
13968
13969 if( *cutoff )
13970 break;
13971
13972 /* update array of active constraints */
13973 if( aggregated )
13974 {
13975 assert(!SCIPconsIsActive(cons0));
13976 assert(SCIPconsIsActive(cons1));
13977 conss[chkind] = NULL;
13978 }
13979 }
13980 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13981 {
13982 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13983 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13984 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13985 nchgcoefs, &aggregated, cutoff) );
13986
13987 if( *cutoff )
13988 break;
13989
13990 /* update array of active constraints */
13991 if( aggregated )
13992 {
13993 assert(!SCIPconsIsActive(cons1));
13994 assert(SCIPconsIsActive(cons0));
13995 conss[c] = NULL;
13996 }
13997 }
13998 }
13999 }
14000
14001 /* free temporary memory */
14002 SCIPfreeBufferArray(scip, &diffidx1minus0);
14003 SCIPfreeBufferArray(scip, &diffidx0minus1);
14004 SCIPfreeBufferArray(scip, &commonidx1);
14005 SCIPfreeBufferArray(scip, &commonidx0);
14006
14007 return SCIP_OKAY;
14008}
14009
14010/** do stuffing presolving on a single constraint */
14011static
14013 SCIP* scip, /**< SCIP data structure */
14014 SCIP_CONS* cons, /**< linear constraint */
14015 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14016 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14017 * constraints using the cheapest variable? */
14018 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14019 int* nfixedvars, /**< pointer to count the total number of fixed variables */
14020 int* nchgbds /**< pointer to count the total number of tightened bounds */
14021 )
14022{
14023 SCIP_CONSDATA* consdata;
14024 SCIP_Real* ratios;
14025 int* varpos;
14026 SCIP_Bool* swapped;
14027 SCIP_VAR** vars;
14028 SCIP_Real* vals;
14029 SCIP_VAR* var;
14030 SCIP_Real lb;
14031 SCIP_Real ub;
14032 SCIP_Real minactivity;
14033 SCIP_Real maxactivity;
14034 SCIP_Real maxcondactivity;
14035 SCIP_Real mincondactivity;
14036 SCIP_Real rhs;
14037 SCIP_Real val;
14038 SCIP_Real obj;
14039 SCIP_Real factor;
14040 SCIP_Bool isminacttight;
14041 SCIP_Bool ismaxacttight;
14042 SCIP_Bool isminsettoinfinity;
14043 SCIP_Bool ismaxsettoinfinity;
14044 SCIP_Bool tryfixing;
14045 int nsingletons;
14046 int idx;
14047 int v;
14048 int nvars;
14049
14050 assert(scip != NULL);
14051 assert(cons != NULL);
14052 assert(nfixedvars != NULL);
14053
14054 consdata = SCIPconsGetData(cons);
14055
14056 /* we only want to run for inequalities */
14057 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14058 return SCIP_OKAY;
14059
14060 if( singlevarstuffing )
14061 {
14062 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
14063 &isminsettoinfinity, &ismaxsettoinfinity);
14064 }
14065 else
14066 {
14067 minactivity = SCIP_INVALID;
14068 maxactivity = SCIP_INVALID;
14069 isminsettoinfinity = FALSE;
14070 ismaxsettoinfinity = FALSE;
14071 }
14072
14073 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14074 * the new maxactivity is minus the old minactivity then
14075 */
14076 if( SCIPisInfinity(scip, consdata->rhs) )
14077 {
14078 rhs = -consdata->lhs;
14079 factor = -1.0;
14080 maxactivity = -minactivity;
14081 ismaxsettoinfinity = isminsettoinfinity;
14082 }
14083 else
14084 {
14085 assert(SCIPisInfinity(scip, -consdata->lhs));
14086 rhs = consdata->rhs;
14087 factor = 1.0;
14088 }
14089
14090 nvars = consdata->nvars;
14091 vars = consdata->vars;
14092 vals = consdata->vals;
14093
14094 /* check for continuous singletons */
14095 if( singletonstuffing )
14096 {
14097 for( v = 0; v < nvars; ++v )
14098 {
14099 var = vars[v];
14100
14103 break;
14104 }
14105 }
14106 else
14107 /* we don't want to go into the next block */
14108 v = nvars;
14109
14110 /* a singleton was found -> perform singleton variable stuffing */
14111 if( v < nvars )
14112 {
14113 assert(singletonstuffing);
14114
14115 SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14116 SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14117 SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14118
14119 tryfixing = TRUE;
14120 nsingletons = 0;
14121 mincondactivity = 0.0;
14122 maxcondactivity = 0.0;
14123
14124 for( v = 0; v < nvars; ++v )
14125 {
14126 var = vars[v];
14127 lb = SCIPvarGetLbGlobal(var);
14128 ub = SCIPvarGetUbGlobal(var);
14129 obj = SCIPvarGetObj(var);
14130 val = factor * vals[v];
14131
14132 assert(!SCIPisZero(scip, val));
14133
14134 /* the variable is a singleton and continuous */
14137 {
14138 if( SCIPisNegative(scip, obj) && val > 0 )
14139 {
14140 /* case 1: obj < 0 and coef > 0 */
14141 if( SCIPisInfinity(scip, -lb) )
14142 {
14143 tryfixing = FALSE;
14144 break;
14145 }
14146
14147 maxcondactivity += val * lb;
14148 mincondactivity += val * lb;
14149 swapped[v] = FALSE;
14150 ratios[nsingletons] = obj / val;
14151 varpos[nsingletons] = v;
14152 nsingletons++;
14153 }
14154 else if( SCIPisPositive(scip, obj) && val < 0 )
14155 {
14156 /* case 2: obj > 0 and coef < 0 */
14157 if( SCIPisInfinity(scip, ub) )
14158 {
14159 tryfixing = FALSE;
14160 break;
14161 }
14162 /* multiply column by (-1) to become case 1.
14163 * now bounds are swapped: ub := -lb, lb := -ub
14164 */
14165
14166 maxcondactivity += val * ub;
14167 mincondactivity += val * ub;
14168 swapped[v] = TRUE;
14169 ratios[nsingletons] = obj / val;
14170 varpos[nsingletons] = v;
14171 nsingletons++;
14172 }
14173 else if( val > 0 )
14174 {
14175 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14176 * we only consider the lower bound for the constants
14177 */
14178 assert(!SCIPisNegative(scip, obj));
14179
14180 if( SCIPisInfinity(scip, -lb) )
14181 {
14182 /* maybe unbounded */
14183 tryfixing = FALSE;
14184 break;
14185 }
14186
14187 maxcondactivity += val * lb;
14188 mincondactivity += val * lb;
14189 }
14190 else
14191 {
14192 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14193 * we only consider the upper bound for the constants
14194 */
14195 assert(!SCIPisPositive(scip, obj));
14196 assert(val < 0);
14197
14198 if( SCIPisInfinity(scip, ub) )
14199 {
14200 /* maybe unbounded */
14201 tryfixing = FALSE;
14202 break;
14203 }
14204
14205 maxcondactivity += val * ub;
14206 mincondactivity += val * ub;
14207 }
14208 }
14209 else
14210 {
14211 /* consider contribution of discrete variables, non-singleton
14212 * continuous variables and variables with more than one lock
14213 */
14214 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14215 {
14216 tryfixing = FALSE;
14217 break;
14218 }
14219
14220 if( val > 0 )
14221 {
14222 maxcondactivity += val * ub;
14223 mincondactivity += val * lb;
14224 }
14225 else
14226 {
14227 maxcondactivity += val * lb;
14228 mincondactivity += val * ub;
14229 }
14230 }
14231 }
14232 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14233 {
14234 SCIP_Real delta;
14235 SCIP_Bool tightened;
14236#ifdef SCIP_DEBUG
14237 int oldnfixedvars = *nfixedvars;
14238 int oldnchgbds = *nchgbds;
14239#endif
14240
14241 SCIPsortRealInt(ratios, varpos, nsingletons);
14242
14243 /* verify which singleton continuous variables can be fixed */
14244 for( v = 0; v < nsingletons; ++v )
14245 {
14246 idx = varpos[v];
14247 var = vars[idx];
14248 val = factor * vals[idx];
14249 lb = SCIPvarGetLbGlobal(var);
14250 ub = SCIPvarGetUbGlobal(var);
14251
14252 assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14253 assert((val < 0) == swapped[idx]);
14254 val = REALABS(val);
14255
14256 /* stop fixing if variable bounds are not finite */
14257 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14258 break;
14259
14263
14264 /* calculate the change in the row activities if this variable changes
14265 * its value from its worst to its best bound
14266 */
14267 if( swapped[idx] )
14268 delta = -(lb - ub) * val;
14269 else
14270 delta = (ub - lb) * val;
14271
14272 assert(!SCIPisNegative(scip, delta));
14273
14274 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14275 {
14276 if( swapped[idx] )
14277 {
14278 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14279 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14280 }
14281 else
14282 {
14283 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14284 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14285 }
14286
14287 if( *cutoff )
14288 break;
14289 if( tightened )
14290 {
14291 (*nfixedvars)++;
14292 }
14293 }
14294 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14295 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14296 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14297 * troubles in case of large bounds.
14298 */
14299 else if( SCIPisLE(scip, rhs, mincondactivity) )
14300 {
14301 if( swapped[idx] )
14302 {
14303 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14304 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14305 }
14306 else
14307 {
14308 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14309 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14310 }
14311
14312 if( *cutoff )
14313 break;
14314 if( tightened )
14315 {
14316 (*nfixedvars)++;
14317 }
14318 }
14319
14320 maxcondactivity += delta;
14321 mincondactivity += delta;
14322 }
14323
14324#ifdef SCIP_DEBUG
14325 if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14326 {
14327 SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14328 }
14329#endif
14330 }
14331
14332 SCIPfreeBufferArray(scip, &swapped);
14333 SCIPfreeBufferArray(scip, &ratios);
14334 SCIPfreeBufferArray(scip, &varpos);
14335 }
14336
14337 /* perform single-variable stuffing:
14338 * for a linear inequality
14339 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14340 * with a_i > 0 and objective coefficients c_i < 0,
14341 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14342 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14343 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14344 * is redundant.
14345 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14346 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14347 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14348 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14349 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14350 * upper bound.
14351 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14352 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14353 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14354 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14355 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14356 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14357 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14358 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14359 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14360 * c_k * ceil((maxactivity - rhs)/val) is still better than
14361 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14362 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14363 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14364 * sign of coefficients in constraint and objective prevent the use of this method.
14365 */
14366 if( singlevarstuffing && !ismaxsettoinfinity )
14367 {
14368 SCIP_Real bestratio = -SCIPinfinity(scip);
14369 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14370 SCIP_Real ratio;
14371 int bestindex = -1;
14372 int bestuplocks = 0;
14373 int bestdownlocks = 1;
14374 int downlocks;
14375 int uplocks;
14376 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14377 SCIPdebug( int oldnchgbds = *nchgbds; )
14378
14379 /* loop over all variables to identify the best and second-best ratio */
14380 for( v = 0; v < nvars; ++v )
14381 {
14382 var = vars[v];
14383 obj = SCIPvarGetObj(var);
14384 val = factor * vals[v];
14385
14386 assert(!SCIPisZero(scip, val));
14387
14388 ratio = obj / val;
14389
14390 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14391 if( !SCIPisNegative(scip, ratio) )
14392 {
14393 bestindex = -1;
14394 break;
14395 }
14396
14397 if( val > 0 )
14398 {
14401 }
14402 else
14403 {
14406 }
14407
14408 /* better ratio, update best candidate
14409 * @todo use some tolerance
14410 * @todo check size of domain and updated ratio for integer variables already?
14411 */
14412 if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14413 || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14415 {
14416 /* best index becomes second-best*/
14417 if( bestindex != -1 )
14418 {
14419 /* second-best index must not have more than 1 uplock */
14420 if( bestuplocks > 1 )
14421 {
14422 bestindex = -1;
14423 break;
14424 }
14425 else
14426 {
14427 secondbestratio = bestratio;
14428 }
14429 }
14430 bestdownlocks = downlocks;
14431 bestuplocks = uplocks;
14432 bestratio = ratio;
14433 bestindex = v;
14434
14435 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14436 * if it is not the best, it has too many uplocks -> not applicable
14437 */
14438 if( bestdownlocks > 0 && bestuplocks > 1 )
14439 {
14440 bestindex = -1;
14441 break;
14442 }
14443 }
14444 else
14445 {
14446 /* non-best index must not have more than 1 uplock */
14447 if( uplocks > 1 )
14448 {
14449 bestindex = -1;
14450 break;
14451 }
14452 /* update second-best ratio */
14453 if( ratio > secondbestratio )
14454 {
14455 secondbestratio = ratio;
14456 }
14457 }
14458 }
14459
14460 /* check if we can apply single variable stuffing */
14461 if( bestindex != -1 && bestdownlocks == 0 )
14462 {
14463 SCIP_Bool tightened = FALSE;
14464 SCIP_Real bounddelta;
14465
14466 var = vars[bestindex];
14467 obj = SCIPvarGetObj(var);
14468 val = factor * vals[bestindex];
14469 lb = SCIPvarGetLbGlobal(var);
14470 ub = SCIPvarGetUbGlobal(var);
14471 tryfixing = TRUE;
14472
14473 if( val < 0 )
14474 {
14475 assert(!SCIPisNegative(scip, obj));
14476
14477 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14478 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14479 {
14480 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14481 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14482 assert(SCIPisPositive(scip, activitydelta));
14483
14484 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14485
14486 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14487 assert(SCIPisPositive(scip, bounddelta));
14488 }
14489 else
14490 bounddelta = (maxactivity - rhs)/-val;
14491
14492 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14493
14494 if( tryfixing )
14495 {
14497
14498 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14499 {
14500 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14501 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14502 }
14503 else
14504 {
14505 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14506 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14507 }
14508 }
14509 }
14510 else
14511 {
14512 assert(!SCIPisPositive(scip, obj));
14513
14514 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14515 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14516 {
14517 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14518 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14519 assert(SCIPisPositive(scip, activitydelta));
14520
14521 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14522
14523 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14524 assert(SCIPisPositive(scip, bounddelta));
14525 }
14526 else
14527 bounddelta = (maxactivity - rhs)/val;
14528
14529 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14530
14531 if( tryfixing )
14532 {
14534
14535 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14536 {
14537 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14538 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14539 }
14540 else
14541 {
14542 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14543 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14544 }
14545 }
14546 }
14547
14548 if( *cutoff )
14549 return SCIP_OKAY;
14550 if( tightened )
14551 {
14553 ++(*nfixedvars);
14554 else
14555 ++(*nchgbds);
14556
14557 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14558 for( v = 0; v < nvars; ++v )
14559 {
14560 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14561 SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14564 SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14565 }
14566 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14567
14568 for( v = 0; v < nvars; ++v )
14569 {
14570 if( v == bestindex )
14571 continue;
14572
14573 if( factor * vals[v] < 0 )
14574 {
14575 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14576 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14577 SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14578 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14579 }
14580 else
14581 {
14582 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14583 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14584 SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14585 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14586 }
14587
14588 if( *cutoff )
14589 return SCIP_OKAY;
14590 if( tightened )
14591 ++(*nfixedvars);
14592 }
14593 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14594 }
14595 }
14596 }
14597
14598 return SCIP_OKAY;
14599}
14600
14601/** applies full dual presolving on variables that only appear in linear constraints */
14602static
14604 SCIP* scip, /**< SCIP data structure */
14605 SCIP_CONS** conss, /**< constraint set */
14606 int nconss, /**< number of constraints */
14607 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14608 int* nchgbds, /**< pointer to count the number of bound changes */
14609 int* nchgvartypes /**< pointer to count the number of variable type changes */
14610 )
14611{
14612 SCIP_Real* redlb;
14613 SCIP_Real* redub;
14614 int* nlocksdown;
14615 int* nlocksup;
14616 SCIP_Bool* isimplint;
14617 SCIP_VAR** origvars;
14618 SCIP_VAR** vars;
14619 SCIP_VAR** conscontvars;
14620 int nvars;
14621 int nbinvars;
14622 int nintvars;
14623 int ncontvars;
14624 int v;
14625 int c;
14626
14627 /* we calculate redundancy bounds with the following meaning:
14628 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14629 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14630 * then:
14631 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14632 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14633 */
14634
14635 /* Additionally, we detect continuous variables that are implicitly integral.
14636 * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14637 * and all constraints (including the bounds as trivial constraints) in which:
14638 * c_j > 0: the variable is down-locked,
14639 * c_j < 0: the variable is up-locked,
14640 * c_j = 0: the variable appears
14641 * have, apart from j, only integer variables with integral coefficients and integral sides.
14642 * This is because then, the value of the variable is either determined by one of its bounds or
14643 * by one of these constraints, and in all cases, the value of the variable is integral.
14644 */
14645
14646 assert(scip != NULL);
14647 assert(nconss == 0 || conss != NULL);
14648 assert(nchgbds != NULL);
14649 assert(!SCIPinProbing(scip));
14650
14651 /* get active variables */
14652 nvars = SCIPgetNVars(scip);
14653 origvars = SCIPgetVars(scip);
14654
14655 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14656 nbinvars = SCIPgetNBinVars(scip);
14657 if( nbinvars == nvars )
14658 return SCIP_OKAY;
14659
14660 /* get number of continuous variables */
14661 ncontvars = SCIPgetNContVars(scip);
14662 nintvars = nvars - ncontvars;
14663
14664 /* copy the variable array since this array might change during the curse of this algorithm */
14665 nvars = nvars - nbinvars;
14666 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14667
14668 /* allocate temporary memory */
14669 SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14670 SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14671 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14672 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14673 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14674 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14675
14676 /* initialize redundancy bounds */
14677 for( v = 0; v < nvars; ++v )
14678 {
14679 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14680 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14681 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14682 }
14683 BMSclearMemoryArray(nlocksdown, nvars);
14684 BMSclearMemoryArray(nlocksup, nvars);
14685
14686 /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14687 * We better not use SCIPisFeasIntegral() in these checks.
14688 */
14689 for( v = 0; v < ncontvars; v++ )
14690 {
14691 SCIP_VAR* var;
14692 SCIP_Real obj;
14693 SCIP_Real lb;
14694 SCIP_Real ub;
14695
14696 var = vars[v + nintvars - nbinvars];
14697 lb = SCIPvarGetLbGlobal(var);
14698 ub = SCIPvarGetUbGlobal(var);
14699
14700 obj = SCIPvarGetObj(var);
14701 if( SCIPisZero(scip, obj) )
14702 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14703 else
14704 {
14705 if( SCIPisPositive(scip, obj) )
14706 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14707 else
14708 {
14709 assert(SCIPisNegative(scip, obj));
14710 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14711 }
14712 }
14713 }
14714
14715 /* scan all constraints */
14716 for( c = 0; c < nconss; ++c )
14717 {
14718 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14719 * part of checked disjunctions)
14720 */
14721 if( SCIPconsIsLocked(conss[c]) )
14722 {
14723 SCIP_CONSDATA* consdata;
14724 SCIP_Bool lhsexists;
14725 SCIP_Bool rhsexists;
14726 SCIP_Bool hasimpliedpotential;
14727 SCIP_Bool integralcoefs;
14728 int nlockspos;
14729 int contvarpos;
14730 int nconscontvars;
14731 int i;
14732
14733 consdata = SCIPconsGetData(conss[c]);
14734 assert(consdata != NULL);
14735
14736 /* get number of times the constraint was locked */
14737 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14738
14739 /* we do not want to include constraints with locked negation (this would be too weird) */
14740 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14741 {
14742 /* mark all continuous variables as not being implicit integral */
14743 for( i = 0; i < consdata->nvars; ++i )
14744 {
14745 SCIP_VAR* var;
14746
14747 var = consdata->vars[i];
14749 {
14750 int contv;
14751 contv = SCIPvarGetProbindex(var) - nintvars;
14752 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14753 isimplint[contv] = FALSE;
14754 }
14755 }
14756 continue;
14757 }
14758
14759 /* check for existing sides */
14760 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14761 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14762
14763 /* count locks and update redundancy bounds */
14764 contvarpos = -1;
14765 nconscontvars = 0;
14766 hasimpliedpotential = FALSE;
14767 integralcoefs = !SCIPconsIsModifiable(conss[c]);
14768
14769 for( i = 0; i < consdata->nvars; ++i )
14770 {
14771 SCIP_VAR* var;
14772 SCIP_Real val;
14773 SCIP_Real minresactivity;
14774 SCIP_Real maxresactivity;
14775 SCIP_Real newredlb;
14776 SCIP_Real newredub;
14777 SCIP_Bool ismintight;
14778 SCIP_Bool ismaxtight;
14779 SCIP_Bool isminsettoinfinity;
14780 SCIP_Bool ismaxsettoinfinity;
14781 int arrayindex;
14782
14783 var = consdata->vars[i];
14784 assert(var != NULL);
14785 val = consdata->vals[i];
14786 assert(!SCIPisZero(scip, val));
14787
14788 /* check if still all integer variables have integral coefficients */
14789 if( SCIPvarIsIntegral(var) )
14790 integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14791
14792 /* we do not need to process binary variables */
14793 if( SCIPvarIsBinary(var) )
14794 continue;
14795
14796 if( SCIPconsIsModifiable(conss[c]) )
14797 {
14798 minresactivity = -SCIPinfinity(scip);
14799 maxresactivity = SCIPinfinity(scip);
14800 isminsettoinfinity = TRUE;
14801 ismaxsettoinfinity = TRUE;
14802 }
14803 else
14804 {
14805 /* calculate residual activity bounds if variable would be fixed to zero */
14806 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14807 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
14808
14809 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14810 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14811 * This is needed, because we do not want to rely on relaxed finite resactivities.
14812 */
14813 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
14814
14815 /* check minresactivity for reliability */
14816 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14817 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14818
14819 /* check maxresactivity for reliability */
14820 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14821 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14822 }
14823
14824 arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14825
14826 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14827
14828 newredlb = redlb[arrayindex];
14829 newredub = redub[arrayindex];
14830 if( val > 0.0 )
14831 {
14832 if( lhsexists )
14833 {
14834 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14835 nlocksdown[arrayindex] += nlockspos;
14836 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14837 }
14838 if( rhsexists )
14839 {
14840 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14841 nlocksup[arrayindex] += nlockspos;
14842 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14843 }
14844 }
14845 else
14846 {
14847 if( lhsexists )
14848 {
14849 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14850 nlocksup[arrayindex] += nlockspos;
14851 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14852 }
14853 if( rhsexists )
14854 {
14855 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14856 nlocksdown[arrayindex] += nlockspos;
14857 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14858 }
14859 }
14860
14861 /* if the variable is integer, we have to round the value to the next integral value */
14862 if( SCIPvarIsIntegral(var) )
14863 {
14864 if( !SCIPisInfinity(scip, newredlb) )
14865 newredlb = SCIPceil(scip, newredlb);
14866 if( !SCIPisInfinity(scip, -newredub) )
14867 newredub = SCIPfloor(scip, newredub);
14868 }
14869
14870 /* update redundancy bounds */
14871 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14872 redub[arrayindex] = MIN(redub[arrayindex], newredub);
14873
14874 /* collect the continuous variables of the constraint */
14876 {
14877 int contv;
14878
14879 assert(nconscontvars < ncontvars);
14880 contvarpos = i;
14881 conscontvars[nconscontvars] = var;
14882 nconscontvars++;
14883
14884 contv = SCIPvarGetProbindex(var) - nintvars;
14885 assert(0 <= contv && contv < ncontvars);
14886 hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14887 }
14888 }
14889
14890 /* update implicit integer status of continuous variables */
14891 if( hasimpliedpotential )
14892 {
14893 if( nconscontvars > 1 || !integralcoefs )
14894 {
14895 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14896 * none of the continuous variables is implicit integer
14897 */
14898 for( i = 0; i < nconscontvars; i++ )
14899 {
14900 int contv;
14901 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14902 assert(0 <= contv && contv < ncontvars);
14903 isimplint[contv] = FALSE;
14904 }
14905 }
14906 else
14907 {
14908 SCIP_VAR* var;
14909 SCIP_Real val;
14910 SCIP_Real absval;
14911 int contv;
14912
14913 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14914 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14915 * side(s) of the constraint is integral
14916 */
14917 assert(nconscontvars == 1);
14918 assert(0 <= contvarpos && contvarpos < consdata->nvars);
14919 var = consdata->vars[contvarpos];
14920 val = consdata->vals[contvarpos];
14921 contv = SCIPvarGetProbindex(var) - nintvars;
14922 assert(0 <= contv && contv < ncontvars);
14923 assert(isimplint[contv]);
14924
14925 absval = REALABS(val);
14926 if( !SCIPisEQ(scip, absval, 1.0) )
14927 isimplint[contv] = FALSE;
14928 else
14929 {
14930 SCIP_Real obj;
14931
14932 obj = SCIPvarGetObj(var);
14933 if( obj * val >= 0.0 && lhsexists )
14934 {
14935 /* the variable may be blocked by the constraint's left hand side */
14936 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14937 }
14938 if( obj * val <= 0.0 && rhsexists )
14939 {
14940 /* the variable may be blocked by the constraint's left hand side */
14941 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14942 }
14943 }
14944 }
14945 }
14946 }
14947 }
14948
14949 /* check if any bounds can be tightened due to optimality */
14950 for( v = 0; v < nvars; ++v )
14951 {
14952 SCIP_VAR* var;
14953 SCIP_Real obj;
14954 SCIP_Bool infeasible;
14955 SCIP_Bool tightened;
14956
14957 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14958 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14959 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14960
14961 var = vars[v];
14962 obj = SCIPvarGetObj(var);
14963 if( !SCIPisPositive(scip, -obj) )
14964 {
14965 /* making the variable as small as possible does not increase the objective:
14966 * check if all down locks of the variables are due to linear constraints;
14967 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
14968 * constraints redundant is huge, we better do nothing for numerical reasons
14969 */
14971 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
14972 && !SCIPisHugeValue(scip, -redlb[v])
14973 && redlb[v] < SCIPvarGetUbGlobal(var) )
14974 {
14975 SCIP_Real ub;
14976
14977 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14978 * -> tighten upper bound to x_v <= redlb[v]
14979 */
14980 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14982 redlb[v]);
14983 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14984 assert(!infeasible);
14985
14986 ub = SCIPvarGetUbGlobal(var);
14987 redub[v] = MIN(redub[v], ub);
14988 if( tightened )
14989 (*nchgbds)++;
14990 }
14991 }
14992 if( !SCIPisPositive(scip, obj) )
14993 {
14994 /* making the variable as large as possible does not increase the objective:
14995 * check if all up locks of the variables are due to linear constraints;
14996 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
14997 * constraints redundant is huge, we better do nothing for numerical reasons
14998 */
15000 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
15001 && !SCIPisHugeValue(scip, redub[v])
15002 && redub[v] > SCIPvarGetLbGlobal(var) )
15003 {
15004 SCIP_Real lb;
15005
15006 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
15007 * -> tighten lower bound to x_v >= redub[v]
15008 */
15009 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
15011 redub[v]);
15012 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15013 assert(!infeasible);
15014
15015 lb = SCIPvarGetLbGlobal(var);
15016 redlb[v] = MAX(redlb[v], lb);
15017 if( tightened )
15018 (*nchgbds)++;
15019 }
15020 }
15021 }
15022
15023 /* upgrade continuous variables to implicit integers */
15024 for( v = nintvars - nbinvars; v < nvars; ++v )
15025 {
15026 SCIP_VAR* var;
15027 SCIP_Bool infeasible;
15028
15029 var = vars[v];
15030 assert(var != NULL);
15031
15033 assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15034 assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15035 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15036
15037 /* we can only conclude implicit integrality if the variable appears in no other constraint */
15038 if( isimplint[v - nintvars + nbinvars]
15039 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15040 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15041 {
15042 /* since we locally copied the variable array we can change the variable type immediately */
15043 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15044 (*nchgvartypes)++;
15045 if( infeasible )
15046 {
15047 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15048 *cutoff = TRUE;
15049
15050 break;
15051 }
15052
15053 SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15055 }
15056 }
15057
15058 /* free temporary memory */
15059 SCIPfreeBufferArray(scip, &conscontvars);
15060 SCIPfreeBufferArray(scip, &isimplint);
15061 SCIPfreeBufferArray(scip, &nlocksup);
15062 SCIPfreeBufferArray(scip, &nlocksdown);
15063 SCIPfreeBufferArray(scip, &redub);
15064 SCIPfreeBufferArray(scip, &redlb);
15065
15066 SCIPfreeBufferArray(scip, &vars);
15067
15068 return SCIP_OKAY;
15069}
15070
15071/** helper function to enforce constraints */
15072static
15074 SCIP* scip, /**< SCIP data structure */
15075 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15076 SCIP_CONS** conss, /**< constraints to process */
15077 int nconss, /**< number of constraints */
15078 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15079 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15080 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15081 )
15082{
15083 SCIP_CONSHDLRDATA* conshdlrdata;
15084 SCIP_Bool checkrelmaxabs;
15085 SCIP_Bool violated;
15086 SCIP_Bool cutoff = FALSE;
15087 int c;
15088
15089 assert(scip != NULL);
15090 assert(conshdlr != NULL);
15091 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15092 assert(result != NULL);
15093
15094 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15095 assert(conshdlrdata != NULL);
15096
15097 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15098
15099 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15100
15101 /* check for violated constraints
15102 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15103 */
15104 *result = SCIP_FEASIBLE;
15105
15106 /* check all useful linear constraints for feasibility */
15107 for( c = 0; c < nusefulconss; ++c )
15108 {
15109 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15110
15111 if( violated )
15112 {
15113 /* insert LP row as cut */
15114 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15115 if ( cutoff )
15116 *result = SCIP_CUTOFF;
15117 else
15118 *result = SCIP_SEPARATED;
15119 }
15120 }
15121
15122 /* check all obsolete linear constraints for feasibility */
15123 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15124 {
15125 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15126
15127 if( violated )
15128 {
15129 /* insert LP row as cut */
15130 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15131 if ( cutoff )
15132 *result = SCIP_CUTOFF;
15133 else
15134 *result = SCIP_SEPARATED;
15135 }
15136 }
15137
15138 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15139
15140 return SCIP_OKAY;
15141}
15142
15143/** adds symmetry information of constraint to a symmetry detection graph */
15144static
15146 SCIP* scip, /**< SCIP pointer */
15147 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15148 SCIP_CONS* cons, /**< constraint */
15149 SYM_GRAPH* graph, /**< symmetry detection graph */
15150 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15151 )
15152{
15153 SCIP_CONSDATA* consdata;
15154 SCIP_VAR** vars;
15155 SCIP_Real* vals;
15156 SCIP_Real constant = 0.0;
15157 SCIP_Real lhs;
15158 SCIP_Real rhs;
15159 int nlocvars;
15160 int nvars;
15161 int i;
15162
15163 assert(scip != NULL);
15164 assert(cons != NULL);
15165 assert(graph != NULL);
15166 assert(success != NULL);
15167
15168 consdata = SCIPconsGetData(cons);
15169 assert(consdata != NULL);
15170
15171 /* get active variables of the constraint */
15172 nvars = SCIPgetNVars(scip);
15173 nlocvars = consdata->nvars;
15174
15175 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
15176 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
15177
15178 for( i = 0; i < nlocvars; ++i )
15179 {
15180 vars[i] = consdata->vars[i];
15181 vals[i] = consdata->vals[i];
15182 }
15183
15184 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15185 lhs = consdata->lhs - constant;
15186 rhs = consdata->rhs - constant;
15187
15188 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15189 * of the same constraint are rated as equal
15190 */
15191 if ( SCIPisInfinity(scip, rhs) )
15192 {
15193 SCIP_Real tmp;
15194 assert(!SCIPisInfinity(scip, -lhs));
15195
15196 for( i = 0; i < nlocvars; ++i )
15197 vals[i] *= -1;
15198 tmp = rhs;
15199 rhs = -lhs;
15200 lhs = -tmp;
15201 }
15202
15203 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
15204 cons, lhs, rhs, success) );
15205
15206 SCIPfreeBufferArray(scip, &vals);
15207 SCIPfreeBufferArray(scip, &vars);
15208
15209 return SCIP_OKAY;
15210}
15211
15212/*
15213 * Callback methods of constraint handler
15214 */
15215
15216/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15217static
15218SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15219{ /*lint --e{715}*/
15220 assert(scip != NULL);
15221 assert(conshdlr != NULL);
15222 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15223
15224 /* call inclusion method of constraint handler */
15226
15227 *valid = TRUE;
15228
15229 return SCIP_OKAY;
15230}
15231
15232/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15233static
15234SCIP_DECL_CONSFREE(consFreeLinear)
15235{ /*lint --e{715}*/
15236 SCIP_CONSHDLRDATA* conshdlrdata;
15237
15238 assert(scip != NULL);
15239 assert(conshdlr != NULL);
15240 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15241
15242 /* free constraint handler data */
15243 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15244 assert(conshdlrdata != NULL);
15245
15246 conshdlrdataFree(scip, &conshdlrdata);
15247
15248 SCIPconshdlrSetData(conshdlr, NULL);
15249
15250 return SCIP_OKAY;
15251}
15252
15253
15254/** initialization method of constraint handler (called after problem was transformed) */
15255static
15256SCIP_DECL_CONSINIT(consInitLinear)
15257{
15258 SCIP_CONSHDLRDATA* conshdlrdata;
15259 int c;
15260
15261 assert(scip != NULL);
15262
15263 /* check for event handler */
15264 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15265 assert(conshdlrdata != NULL);
15266 assert(conshdlrdata->eventhdlr != NULL);
15267 assert(nconss == 0 || conss != NULL);
15268
15269 conshdlrdata->naddconss = 0;
15270
15271 /* catch events for the constraints */
15272 for( c = 0; c < nconss; ++c )
15273 {
15274 /* catch all events */
15275 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15276 }
15277
15278 return SCIP_OKAY;
15279}
15280
15281
15282/** deinitialization method of constraint handler (called before transformed problem is freed) */
15283static
15284SCIP_DECL_CONSEXIT(consExitLinear)
15285{
15286 SCIP_CONSHDLRDATA* conshdlrdata;
15287 int c;
15288
15289 assert(scip != NULL);
15290
15291 /* check for event handler */
15292 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15293 assert(conshdlrdata != NULL);
15294 assert(conshdlrdata->eventhdlr != NULL);
15295
15296 /* drop events for the constraints */
15297 for( c = nconss - 1; c >= 0; --c )
15298 {
15299 SCIP_CONSDATA* consdata;
15300
15301 consdata = SCIPconsGetData(conss[c]);
15302 assert(consdata != NULL);
15303
15304 if( consdata->eventdata != NULL )
15305 {
15306 /* drop all events */
15307 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15308 assert(consdata->eventdata == NULL);
15309 }
15310 }
15311
15312 return SCIP_OKAY;
15313}
15314
15315/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15316static
15318 SCIP* scip, /**< SCIP data structure */
15319 SCIP_Real lhs, /**< left hand side */
15320 SCIP_Real rhs /**< right hand side */
15321 )
15322{
15323 assert(scip != NULL);
15324
15325 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15326}
15327
15328/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15329static
15331 SCIP* scip, /**< SCIP data structure */
15332 SCIP_Real x /**< value */
15333 )
15334{
15335 assert(scip != NULL);
15336
15337 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15338}
15339
15340/** performs linear constraint type classification as used for MIPLIB
15341 *
15342 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15343 *
15344 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15345 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15346 * Similarly, if specialized constraints were created through the API, these are currently not present.
15347 */
15349 SCIP* scip, /**< SCIP data structure */
15350 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15351 )
15352{
15353 int c;
15354 SCIP_CONSHDLR* conshdlr;
15355 SCIP_CONS** conss;
15356 int nconss;
15357
15358 assert(scip != NULL);
15359 assert(linconsstats != NULL);
15360 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15361 assert(conshdlr != NULL);
15362
15364 {
15365 conss = SCIPgetConss(scip);
15366 nconss = SCIPgetNConss(scip);
15367 }
15368 else
15369 {
15370 conss = SCIPconshdlrGetConss(conshdlr);
15371 nconss = SCIPconshdlrGetNConss(conshdlr);
15372 }
15373
15374 /* reset linear constraint type classification */
15375 SCIPlinConsStatsReset(linconsstats);
15376
15377 /* loop through all constraints */
15378 for( c = 0; c < nconss; c++ )
15379 {
15380 SCIP_CONS* cons;
15381 SCIP_CONSDATA* consdata;
15382 SCIP_Real lhs;
15383 SCIP_Real rhs;
15384 int i;
15385
15386 /* get constraint */
15387 cons = conss[c];
15388 assert(cons != NULL);
15389
15390 /* skip constraints that are not handled by the constraint handler */
15391 if( SCIPconsGetHdlr(cons) != conshdlr )
15392 continue;
15393
15394 /* get constraint data */
15395 consdata = SCIPconsGetData(cons);
15396 assert(consdata != NULL);
15397 rhs = consdata->rhs;
15398 lhs = consdata->lhs;
15399
15400 /* merge multiples and delete variables with zero coefficient */
15401 SCIP_CALL( mergeMultiples(scip, cons) );
15402 for( i = 0; i < consdata->nvars; i++ )
15403 {
15404 assert(!SCIPisZero(scip, consdata->vals[i]));
15405 }
15406
15407 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15408 if( consdata->nvars == 0 )
15409 {
15410 SCIPdebugMsg(scip, "classified as EMPTY: ");
15413
15414 continue;
15415 }
15416
15417 /* is constraint of type SCIP_CONSTYPE_FREE? */
15418 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15419 {
15420 SCIPdebugMsg(scip, "classified as FREE: ");
15423
15424 continue;
15425 }
15426
15427 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15428 if( consdata->nvars == 1 )
15429 {
15430 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15433
15434 continue;
15435 }
15436
15437 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15438 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15439 {
15440 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15443
15444 continue;
15445 }
15446
15447 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15448 if( consdata->nvars == 2 )
15449 {
15450 SCIP_LINCONSTYPE constype;
15451
15452 /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15453 if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15454 && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15455 {
15456 constype = SCIP_LINCONSTYPE_PRECEDENCE;
15457 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15458 }
15459 else
15460 {
15461 constype = SCIP_LINCONSTYPE_VARBOUND;
15462 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15463 }
15465
15466 SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15467
15468 continue;
15469 }
15470
15471 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15472 {
15473 SCIP_Real scale;
15474 SCIP_Real b;
15475 SCIP_Bool unmatched;
15476 int nnegbinvars;
15477
15478 unmatched = FALSE;
15479 nnegbinvars = 0;
15480
15481 scale = REALABS(consdata->vals[0]);
15482
15483 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15484 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15485 {
15486 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15487 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15488 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15489 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15490
15491 if( consdata->vals[i] < 0.0 )
15492 nnegbinvars++;
15493 }
15494
15495 if( !unmatched )
15496 {
15497 if( SCIPisEQ(scip, lhs, rhs) )
15498 {
15499 b = rhs/scale + nnegbinvars;
15500 if( SCIPisEQ(scip, 1.0, b) )
15501 {
15502 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15505
15506 continue;
15507 }
15508 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15509 {
15510 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15513
15514 continue;
15515 }
15516 }
15517
15518 /* compute right hand side divided by scale */
15519 if( !SCIPisInfinity(scip, rhs) )
15520 b = rhs/scale + nnegbinvars;
15521 else
15522 b = SCIPinfinity(scip);
15523
15524 if( SCIPisEQ(scip, 1.0, b) )
15525 {
15526 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15529
15530 /* relax right hand side to prevent further classifications */
15531 rhs = SCIPinfinity(scip);
15532 }
15533 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15534 {
15535 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15537
15539
15540 /* relax right hand side to prevent further classifications */
15541 rhs = SCIPinfinity(scip);
15542 }
15543
15544 if( !SCIPisInfinity(scip, lhs) )
15545 b = lhs/scale + nnegbinvars;
15546 else
15547 b = SCIPinfinity(scip);
15548
15549 if( SCIPisEQ(scip, 1.0, b) )
15550 {
15551 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15554
15555 /* relax left hand side to prevent further classifications */
15556 lhs = -SCIPinfinity(scip);
15557 }
15558
15559 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15560 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15561 continue;
15562 }
15563 }
15564
15565 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15566 /* @todo If coefficients or rhs are not integral, we currently do not check
15567 * if the constraint could be scaled (finitely), such that they are.
15568 */
15569 {
15570 SCIP_Real b;
15571 SCIP_Bool unmatched;
15572
15573 b = rhs;
15574 unmatched = FALSE;
15575 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15576 {
15577 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15578 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15579 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15580 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15581
15582 if( SCIPisNegative(scip, consdata->vals[i]) )
15583 b -= consdata->vals[i];
15584 }
15585 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15586
15587 if( !unmatched )
15588 {
15589 if( SCIPisEQ(scip, lhs, rhs) )
15590 {
15591 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15593
15595
15596 continue;
15597 }
15598 else
15599 {
15600 SCIP_Bool matched;
15601
15602 matched = FALSE;
15603 for( i = 0; i < consdata->nvars && !matched; i++ )
15604 {
15605 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15606 }
15607
15608 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15611 }
15612
15613 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15614 if( SCIPisInfinity(scip, -lhs) )
15615 continue;
15616 else
15617 rhs = SCIPinfinity(scip);
15618 }
15619 }
15620
15621 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15622 {
15623 SCIP_Real b;
15624 SCIP_Bool unmatched;
15625
15626 unmatched = FALSE;
15627
15628 b = rhs;
15629 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15630
15631 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15632 {
15633 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15634 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15635 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15636 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15637 }
15638
15639 if( !unmatched )
15640 {
15641 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15644
15645 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15646 if( SCIPisInfinity(scip, -lhs) )
15647 continue;
15648 else
15649 rhs = SCIPinfinity(scip);
15650 }
15651 }
15652
15653 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15654 {
15655 SCIP_Bool unmatched;
15656
15657 unmatched = FALSE;
15658 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15659 {
15660 if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15661 && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15662 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15663 unmatched = TRUE;
15664 }
15665
15666 if( !unmatched )
15667 {
15668 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15671
15672 continue;
15673 }
15674 }
15675
15676 /* no special structure detected */
15677 SCIPdebugMsg(scip, "classified as GENERAL: ");
15679 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15680 }
15681
15682 return SCIP_OKAY;
15683}
15684
15685
15686/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15687static
15688SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15689{ /*lint --e{715}*/
15690 int c;
15691#ifdef SCIP_STATISTIC
15692 SCIP_CONSHDLRDATA* conshdlrdata;
15693 int ngoodconss;
15694 int nallconss;
15695#endif
15696
15697 /* delete all linear constraints that were upgraded to a more specific constraint type;
15698 * make sure, only active variables remain in the remaining constraints
15699 */
15700 assert(scip != NULL);
15701
15702#ifdef SCIP_STATISTIC
15703 /* count number of well behaved linear constraints */
15704 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15705 assert(conshdlrdata != NULL);
15706
15707 ngoodconss = 0;
15708 nallconss = 0;
15709
15710 for( c = 0; c < nconss; ++c )
15711 {
15712 SCIP_CONSDATA* consdata;
15713
15714 if( SCIPconsIsDeleted(conss[c]) )
15715 continue;
15716
15717 consdata = SCIPconsGetData(conss[c]);
15718 assert(consdata != NULL);
15719
15720 if( consdata->upgraded )
15721 continue;
15722
15723 nallconss++;
15724
15726
15727 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15728 ngoodconss++;
15729 }
15730 if( nallconss )
15731 {
15732 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15733 }
15734#endif
15735
15736 for( c = 0; c < nconss; ++c )
15737 {
15738 SCIP_CONSDATA* consdata;
15739
15740 if( SCIPconsIsDeleted(conss[c]) )
15741 continue;
15742
15743 consdata = SCIPconsGetData(conss[c]);
15744 assert(consdata != NULL);
15745
15746 if( consdata->upgraded )
15747 {
15748 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15749 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15750 */
15751 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15752 }
15753 else
15754 {
15755 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15756 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15757 }
15758 }
15759
15760 return SCIP_OKAY;
15761}
15762
15763/** solving process initialization method of constraint handler */
15764static
15765SCIP_DECL_CONSINITSOL(consInitsolLinear)
15766{ /*lint --e{715}*/
15767 /* add nlrow representation to NLP, if NLP had been constructed */
15769 {
15770 int c;
15771 for( c = 0; c < nconss; ++c )
15772 {
15773 SCIP_CALL( addNlrow(scip, conss[c]) );
15774 }
15775 }
15776
15777 return SCIP_OKAY;
15778}
15779
15780/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15781static
15782SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15783{ /*lint --e{715}*/
15784 int c;
15785
15786 assert(scip != NULL);
15787
15788 /* release the rows and nlrows of all constraints */
15789 for( c = 0; c < nconss; ++c )
15790 {
15791 SCIP_CONSDATA* consdata;
15792
15793 consdata = SCIPconsGetData(conss[c]);
15794 assert(consdata != NULL);
15795
15796 if( consdata->row != NULL )
15797 {
15798 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15799 }
15800
15801 if( consdata->nlrow != NULL )
15802 {
15803 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15804 }
15805 }
15806
15807 /* if this is a restart, convert cutpool rows into linear constraints */
15808 if( restart )
15809 {
15810 int ncutsadded;
15811
15812 ncutsadded = 0;
15813
15814 /* create out of all active cuts in cutpool linear constraints */
15815 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15816
15817 if( ncutsadded > 0 )
15818 {
15820 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15821 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15822 * line correctly
15823 */
15825 }
15826 }
15827
15828 return SCIP_OKAY;
15829}
15830
15831
15832/** constraint activation notification method of constraint handler */
15833static
15834SCIP_DECL_CONSACTIVE(consActiveLinear)
15835{ /*lint --e{715}*/
15836 assert(cons != NULL);
15837
15839 {
15840 SCIP_CALL( addNlrow(scip, cons) );
15841 }
15842
15843 return SCIP_OKAY;
15844}
15845
15846/** constraint deactivation notification method of constraint handler */
15847static
15848SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15849{ /*lint --e{715}*/
15850 SCIP_CONSDATA* consdata;
15851
15852 assert(scip != NULL);
15853 assert(conshdlr != NULL);
15854 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15855 assert(cons != NULL );
15856
15857 /* get constraint data */
15858 consdata = SCIPconsGetData(cons);
15859 assert(consdata != NULL);
15860
15861 if( SCIPconsIsDeleted(cons) )
15862 {
15863 SCIP_CONSHDLRDATA* conshdlrdata;
15864
15865 /* check for event handler */
15866 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15867 assert(conshdlrdata != NULL);
15868 assert(conshdlrdata->eventhdlr != NULL);
15869
15870 /* free event data */
15871 if( consdata->eventdata != NULL )
15872 {
15873 /* drop bound change events of variables */
15874 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15875 }
15876 assert(consdata->eventdata == NULL);
15877 }
15878
15879 /* remove row from NLP, if still in solving
15880 * if we are in exitsolve, the whole NLP will be freed anyway
15881 */
15882 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15883 {
15884 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15885 }
15886
15887 return SCIP_OKAY;
15888}
15889
15890
15891/** frees specific constraint data */
15892static
15893SCIP_DECL_CONSDELETE(consDeleteLinear)
15894{ /*lint --e{715}*/
15895 assert(scip != NULL);
15896 assert(conshdlr != NULL);
15897 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15898
15899 if( (*consdata)->eventdata != NULL )
15900 {
15901 SCIP_CONSHDLRDATA* conshdlrdata;
15902
15903 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15904 assert(conshdlrdata != NULL);
15905
15906 /* drop all events */
15907 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15908 assert((*consdata)->eventdata == NULL);
15909 }
15910
15911 /* free linear constraint */
15912 SCIP_CALL( consdataFree(scip, consdata) );
15913
15914 return SCIP_OKAY;
15915}
15916
15917
15918/** transforms constraint data into data belonging to the transformed problem */
15919static
15920SCIP_DECL_CONSTRANS(consTransLinear)
15921{ /*lint --e{715}*/
15922 SCIP_CONSDATA* sourcedata;
15923 SCIP_CONSDATA* targetdata;
15924
15925 /*debugMsg(scip, "Trans method of linear constraints\n");*/
15926
15927 assert(scip != NULL);
15928 assert(conshdlr != NULL);
15929 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15931 assert(sourcecons != NULL);
15932 assert(targetcons != NULL);
15933
15934 sourcedata = SCIPconsGetData(sourcecons);
15935 assert(sourcedata != NULL);
15936 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15937
15938 /* create linear constraint data for target constraint */
15939 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15940
15941#ifndef NDEBUG
15942 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15943 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15944 {
15945 int n;
15946 for(n = targetdata->nvars - 1; n >= 0; --n )
15947 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15948 }
15949#endif
15950
15951 /* create target constraint */
15952 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15953 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15954 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15955 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15956 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15957
15958 return SCIP_OKAY;
15959}
15960
15961
15962/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15963static
15964SCIP_DECL_CONSINITLP(consInitlpLinear)
15965{ /*lint --e{715}*/
15966 int c;
15967
15968 assert(scip != NULL);
15969 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15970
15971 *infeasible = FALSE;
15972
15973 for( c = 0; c < nconss && !(*infeasible); ++c )
15974 {
15975 assert(SCIPconsIsInitial(conss[c]));
15976 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15977 }
15978
15979 return SCIP_OKAY;
15980}
15981
15982
15983/** separation method of constraint handler for LP solutions */
15984static
15985SCIP_DECL_CONSSEPALP(consSepalpLinear)
15986{ /*lint --e{715}*/
15987 SCIP_CONSHDLRDATA* conshdlrdata;
15988 SCIP_Real loclowerbound;
15989 SCIP_Real glblowerbound;
15990 SCIP_Real cutoffbound;
15991 SCIP_Real maxbound;
15992 SCIP_Bool separatecards;
15993 SCIP_Bool cutoff;
15994 int c;
15995 int depth;
15996 int nrounds;
15997 int maxsepacuts;
15998 int ncuts;
15999
16000 assert(scip != NULL);
16001 assert(conshdlr != NULL);
16002 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16003 assert(result != NULL);
16004
16005 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16006 assert(conshdlrdata != NULL);
16007 depth = SCIPgetDepth(scip);
16008 nrounds = SCIPgetNSepaRounds(scip);
16009
16010 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16011
16012 *result = SCIP_DIDNOTRUN;
16013
16014 /* only call the separator a given number of times at each node */
16015 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16016 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16017 return SCIP_OKAY;
16018
16019 /* get the maximal number of cuts allowed in a separation round */
16020 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16021
16022 /* check if we want to produce knapsack cardinality cuts at this node */
16023 loclowerbound = SCIPgetLocalLowerbound(scip);
16024 glblowerbound = SCIPgetLowerbound(scip);
16025 cutoffbound = SCIPgetCutoffbound(scip);
16026 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16027 separatecards = SCIPisLE(scip, loclowerbound, maxbound);
16028 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
16029
16030 *result = SCIP_DIDNOTFIND;
16031 ncuts = 0;
16032 cutoff = FALSE;
16033
16034 /* check all useful linear constraints for feasibility */
16035 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16036 {
16037 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16038 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16039 }
16040
16041 /* adjust return value */
16042 if( cutoff )
16043 *result = SCIP_CUTOFF;
16044 else if( ncuts > 0 )
16045 *result = SCIP_SEPARATED;
16046
16047 /* combine linear constraints to get more cuts */
16048 /**@todo further cuts of linear constraints */
16049
16050 return SCIP_OKAY;
16051}
16052
16053
16054/** separation method of constraint handler for arbitrary primal solutions */
16055static
16056SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16057{ /*lint --e{715}*/
16058 SCIP_CONSHDLRDATA* conshdlrdata;
16059 int c;
16060 int depth;
16061 int nrounds;
16062 int maxsepacuts;
16063 int ncuts;
16064 SCIP_Bool cutoff;
16065
16066 assert(scip != NULL);
16067 assert(conshdlr != NULL);
16068 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16069 assert(result != NULL);
16070
16071 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16072 assert(conshdlrdata != NULL);
16073 depth = SCIPgetDepth(scip);
16074 nrounds = SCIPgetNSepaRounds(scip);
16075
16076 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16077
16078 *result = SCIP_DIDNOTRUN;
16079
16080 /* only call the separator a given number of times at each node */
16081 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16082 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16083 return SCIP_OKAY;
16084
16085 /* get the maximal number of cuts allowed in a separation round */
16086 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16087
16088 *result = SCIP_DIDNOTFIND;
16089 ncuts = 0;
16090 cutoff = FALSE;
16091
16092 /* check all useful linear constraints for feasibility */
16093 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16094 {
16095 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16096 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16097 }
16098
16099 /* adjust return value */
16100 if( cutoff )
16101 *result = SCIP_CUTOFF;
16102 else if( ncuts > 0 )
16103 *result = SCIP_SEPARATED;
16104
16105 /* combine linear constraints to get more cuts */
16106 /**@todo further cuts of linear constraints */
16107
16108 return SCIP_OKAY;
16109}
16110
16111
16112/** constraint enforcing method of constraint handler for LP solutions */
16113static
16114SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16115{ /*lint --e{715}*/
16116 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16117
16118 return SCIP_OKAY;
16119}
16120
16121/** constraint enforcing method of constraint handler for relaxation solutions */
16122static
16123SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16124{ /*lint --e{715}*/
16125 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16126
16127 return SCIP_OKAY;
16128}
16129
16130/** constraint enforcing method of constraint handler for pseudo solutions */
16131static
16132SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16133{ /*lint --e{715}*/
16134 SCIP_CONSHDLRDATA* conshdlrdata;
16135 SCIP_Bool checkrelmaxabs;
16136 SCIP_Bool violated;
16137 int c;
16138
16139 assert(scip != NULL);
16140 assert(conshdlr != NULL);
16141 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16142 assert(result != NULL);
16143
16144 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16145 assert(conshdlrdata != NULL);
16146
16147 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16148
16149 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16150
16151 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16152 if( objinfeasible )
16153 {
16154 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16155
16156 *result = SCIP_DIDNOTRUN;
16157 return SCIP_OKAY;
16158 }
16159
16160 /* check all linear constraints for feasibility */
16161 violated = FALSE;
16162 for( c = 0; c < nconss && !violated; ++c )
16163 {
16164 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16165 }
16166
16167 if( violated )
16168 *result = SCIP_INFEASIBLE;
16169 else
16170 *result = SCIP_FEASIBLE;
16171
16172 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16173
16174 return SCIP_OKAY;
16175}
16176
16177
16178/** feasibility check method of constraint handler for integral solutions */
16179static
16180SCIP_DECL_CONSCHECK(consCheckLinear)
16181{ /*lint --e{715}*/
16182 SCIP_CONSHDLRDATA* conshdlrdata;
16183 SCIP_Bool checkrelmaxabs;
16184 int c;
16185
16186 assert(scip != NULL);
16187 assert(conshdlr != NULL);
16188 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16189 assert(result != NULL);
16190
16191 *result = SCIP_FEASIBLE;
16192
16193 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16194 assert(conshdlrdata != NULL);
16195
16196 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16197
16198 /*debugMsg(scip, "Check method of linear constraints\n");*/
16199
16200 /* check all linear constraints for feasibility */
16201 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16202 {
16203 SCIP_Bool violated = FALSE;
16204 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16205
16206 if( violated )
16207 {
16208 *result = SCIP_INFEASIBLE;
16209
16210 if( printreason )
16211 {
16212 SCIP_CONSDATA* consdata;
16213 SCIP_Real activity;
16214
16215 consdata = SCIPconsGetData(conss[c]);
16216 assert( consdata != NULL);
16217
16218 activity = consdataGetActivity(scip, consdata, sol);
16219
16220 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16221 SCIPinfoMessage(scip, NULL, ";\n");
16222
16223 if( activity == SCIP_INVALID ) /*lint !e777*/
16224 SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16225 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16226 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16227 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16228 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16229 }
16230 }
16231 }
16232
16233 return SCIP_OKAY;
16234}
16235
16236
16237/** domain propagation method of constraint handler */
16238static
16239SCIP_DECL_CONSPROP(consPropLinear)
16240{ /*lint --e{715}*/
16241 SCIP_CONSHDLRDATA* conshdlrdata;
16242 SCIP_Bool rangedrowpropagation = FALSE;
16243 SCIP_Bool tightenbounds;
16244 SCIP_Bool cutoff;
16245
16246 int nchgbds;
16247 int i;
16248
16249 assert(scip != NULL);
16250 assert(conshdlr != NULL);
16251 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16252 assert(result != NULL);
16253
16254 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16255 assert(conshdlrdata != NULL);
16256
16257 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16258
16259 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16260 if( SCIPinProbing(scip) )
16261 tightenbounds = TRUE;
16262 else
16263 {
16264 int depth;
16265 int propfreq;
16266 int tightenboundsfreq;
16267 int rangedrowfreq;
16268
16269 depth = SCIPgetDepth(scip);
16270 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16271 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16272 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16273 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16274
16275 /* check if we want to do ranged row propagation */
16276 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16277 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16278 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16279 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16280 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16281 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16282 }
16283
16284 cutoff = FALSE;
16285 nchgbds = 0;
16286
16287 /* process constraints marked for propagation */
16288 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16289 {
16291 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16292 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16293 }
16294
16295 /* adjust result code */
16296 if( cutoff )
16297 *result = SCIP_CUTOFF;
16298 else if( nchgbds > 0 )
16299 *result = SCIP_REDUCEDDOM;
16300 else
16301 *result = SCIP_DIDNOTFIND;
16302
16303 return SCIP_OKAY;
16304}
16305
16306
16307#define MAXCONSPRESOLROUNDS 10
16308/** presolving method of constraint handler */
16309static
16310SCIP_DECL_CONSPRESOL(consPresolLinear)
16311{ /*lint --e{715}*/
16312 SCIP_CONSHDLRDATA* conshdlrdata;
16313 SCIP_CONS* cons;
16314 SCIP_CONSDATA* consdata;
16315 SCIP_Real minactivity;
16316 SCIP_Real maxactivity;
16317 SCIP_Bool isminacttight;
16318 SCIP_Bool ismaxacttight;
16319 SCIP_Bool isminsettoinfinity;
16320 SCIP_Bool ismaxsettoinfinity;
16321 SCIP_Bool cutoff;
16322 int oldnfixedvars;
16323 int oldnaggrvars;
16324 int oldnchgbds;
16325 int oldndelconss;
16326 int oldnupgdconss;
16327 int oldnchgcoefs;
16328 int oldnchgsides;
16329 int firstchange;
16330 int firstupgradetry;
16331 int c;
16332
16333 assert(scip != NULL);
16334 assert(conshdlr != NULL);
16335 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16336 assert(result != NULL);
16337
16338 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16339
16340 /* remember old preprocessing counters */
16341 cutoff = FALSE;
16342 oldnfixedvars = *nfixedvars;
16343 oldnaggrvars = *naggrvars;
16344 oldnchgbds = *nchgbds;
16345 oldndelconss = *ndelconss;
16346 oldnupgdconss = *nupgdconss;
16347 oldnchgcoefs = *nchgcoefs;
16348 oldnchgsides = *nchgsides;
16349
16350 /* get constraint handler data */
16351 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16352 assert(conshdlrdata != NULL);
16353
16354 /* process single constraints */
16355 firstchange = INT_MAX;
16356 firstupgradetry = INT_MAX;
16357 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16358 {
16359 int npresolrounds;
16360 SCIP_Bool infeasible;
16361
16362 infeasible = FALSE;
16363
16364 cons = conss[c];
16365 assert(SCIPconsIsActive(cons));
16366 consdata = SCIPconsGetData(cons);
16367 assert(consdata != NULL);
16368
16369 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16370 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16371 {
16372 consdata->lhs = consdata->rhs;
16373 assert(consdata->row == NULL);
16374 }
16375
16376 if( consdata->eventdata == NULL )
16377 {
16378 /* catch bound change events of variables */
16379 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16380 assert(consdata->eventdata != NULL);
16381 }
16382
16383 /* constraint should not be already presolved in the initial round */
16384 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16385 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16386 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16387 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16388
16389 /* incorporate fixings and aggregations in constraint */
16390 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16391
16392 if( infeasible )
16393 {
16394 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16395 cutoff = TRUE;
16396 break;
16397 }
16398
16399 assert(consdata->removedfixings);
16400
16401 /* we can only presolve linear constraints, that are not modifiable */
16402 if( SCIPconsIsModifiable(cons) )
16403 continue;
16404
16405 /* remember the first changed constraint to begin the next aggregation round with */
16406 if( firstchange == INT_MAX && consdata->changed )
16407 firstchange = c;
16408
16409 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16410 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16411 firstupgradetry = c;
16412
16413 /* check, if constraint is already preprocessed */
16414 if( consdata->presolved )
16415 continue;
16416
16417 assert(SCIPconsIsActive(cons));
16418
16419 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16421
16422 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16423 * to avoid nearly infinite cycling due to very small bound changes)
16424 */
16425 npresolrounds = 0;
16426 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16427 {
16428 assert(!cutoff);
16429 npresolrounds++;
16430
16431 /* mark constraint being presolved and propagated */
16432 consdata->presolved = TRUE;
16434
16435 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16436
16437 if( infeasible )
16438 {
16439 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16440 cutoff = TRUE;
16441 break;
16442 }
16443
16444 /* tighten left and right hand side due to integrality */
16445 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16446
16447 if( infeasible )
16448 {
16449 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16450 cutoff = TRUE;
16451 break;
16452 }
16453
16454 /* check bounds */
16455 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16456 {
16457 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16458 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16459 cutoff = TRUE;
16460 break;
16461 }
16462
16463 /* tighten variable's bounds */
16464 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16465 if( cutoff )
16466 break;
16467
16468 /* check for fixed variables */
16469 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16470 if( cutoff )
16471 break;
16472
16473 /* check constraint for infeasibility and redundancy */
16474 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
16475 &isminsettoinfinity, &ismaxsettoinfinity);
16476 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16477 {
16478 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16479 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16480 cutoff = TRUE;
16481 break;
16482 }
16483 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16484 {
16485 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16486 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16487 SCIP_CALL( SCIPdelCons(scip, cons) );
16488 assert(!SCIPconsIsActive(cons));
16489
16490 if( !consdata->upgraded )
16491 (*ndelconss)++;
16492 break;
16493 }
16494 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16495 {
16496 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16497 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16498 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16499 if( !consdata->upgraded )
16500 (*nchgsides)++;
16501 }
16502 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16503 {
16504 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16505 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16507 if( !consdata->upgraded )
16508 (*nchgsides)++;
16509 }
16510
16511 /* handle empty constraint */
16512 if( consdata->nvars == 0 )
16513 {
16514 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16515 {
16516 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16517 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16518 cutoff = TRUE;
16519 }
16520 else
16521 {
16522 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16523 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16524 SCIP_CALL( SCIPdelCons(scip, cons) );
16525 assert(!SCIPconsIsActive(cons));
16526
16527 if( !consdata->upgraded )
16528 (*ndelconss)++;
16529 }
16530 break;
16531 }
16532
16533 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16534 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16535
16536 /* try to simplify inequalities */
16537 if( conshdlrdata->simplifyinequalities )
16538 {
16539 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16540
16541 if( cutoff )
16542 break;
16543 }
16544
16545 /* aggregation variable in equations */
16546 if( conshdlrdata->aggregatevariables )
16547 {
16548 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16549 if( cutoff )
16550 break;
16551 }
16552 }
16553
16554 if( !cutoff && !SCIPisStopped(scip) )
16555 {
16556 /* perform ranged row propagation */
16557 if( conshdlrdata->rangedrowpropagation )
16558 {
16559 int lastnfixedvars;
16560
16561 lastnfixedvars = *nfixedvars;
16562
16563 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16564 if( !cutoff )
16565 {
16566 if( lastnfixedvars < *nfixedvars )
16567 {
16568 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16569 }
16570 }
16571 }
16572
16573 /* extract cliques from constraint */
16574 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16575 {
16576 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16577 nfixedvars, nchgbds, &cutoff) );
16578
16579 /* check if the constraint got redundant or infeasible */
16580 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16581 {
16582 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16583 {
16584 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16585 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16586 cutoff = TRUE;
16587 }
16588 else
16589 {
16590 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16591 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16592 SCIP_CALL( SCIPdelCons(scip, cons) );
16593 assert(!SCIPconsIsActive(cons));
16594
16595 if( !consdata->upgraded )
16596 (*ndelconss)++;
16597 }
16598 }
16599 }
16600
16601 /* convert special equalities */
16602 if( !cutoff && SCIPconsIsActive(cons) )
16603 {
16604 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16605 }
16606
16607 /* apply dual presolving for variables that appear in only one constraint */
16608 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16609 {
16610 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16611 }
16612
16613 /* check if an inequality is parallel to the objective function */
16614 if( !cutoff && SCIPconsIsActive(cons) )
16615 {
16616 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16617 }
16618
16619 /* remember the first changed constraint to begin the next aggregation round with */
16620 if( firstchange == INT_MAX && consdata->changed )
16621 firstchange = c;
16622
16623 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16624 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16625 firstupgradetry = c;
16626 }
16627
16628 /* singleton column stuffing */
16629 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16630 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16631 {
16632 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16633 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16634
16635 /* handle empty constraint */
16636 if( consdata->nvars == 0 )
16637 {
16638 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16639 {
16640 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16641 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16642 cutoff = TRUE;
16643 }
16644 else
16645 {
16646 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16647 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16648 SCIP_CALL( SCIPdelCons(scip, cons) );
16649 assert(!SCIPconsIsActive(cons));
16650
16651 if( !consdata->upgraded )
16652 (*ndelconss)++;
16653 }
16654 break;
16655 }
16656 }
16657 }
16658
16659 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16660 * only apply this expensive procedure in exhaustive presolving timing
16661 */
16662 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16663 {
16664 assert(firstchange >= 0);
16665
16666 if( firstchange < nconss && conshdlrdata->presolusehashing )
16667 {
16668 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16669 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16670 ndelconss, nchgsides) );
16671 }
16672
16673 if( firstchange < nconss && conshdlrdata->presolpairwise )
16674 {
16675 SCIP_CONS** usefulconss;
16676 int nusefulconss;
16677 int firstchangenew;
16678 SCIP_Longint npaircomparisons;
16679
16680 npaircomparisons = 0;
16681 oldndelconss = *ndelconss;
16682 oldnchgsides = *nchgsides;
16683 oldnchgcoefs = *nchgcoefs;
16684
16685 /* allocate temporary memory */
16686 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16687
16688 nusefulconss = 0;
16689 firstchangenew = -1;
16690 for( c = 0; c < nconss; ++c )
16691 {
16692 /* update firstchange */
16693 if( c == firstchange )
16694 firstchangenew = nusefulconss;
16695
16696 /* ignore inactive and modifiable constraints */
16697 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16698 continue;
16699
16700 usefulconss[nusefulconss] = conss[c];
16701 ++nusefulconss;
16702 }
16703 firstchange = firstchangenew;
16704 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16705
16706 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16707 {
16708 /* constraint has become inactive or modifiable during pairwise presolving */
16709 if( usefulconss[c] == NULL )
16710 continue;
16711
16712 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16713
16714 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16715 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16716 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16717
16718 if( npaircomparisons > conshdlrdata->nmincomparisons )
16719 {
16720 assert(npaircomparisons > 0);
16721 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16722 break;
16723 oldndelconss = *ndelconss;
16724 oldnchgsides = *nchgsides;
16725 oldnchgcoefs = *nchgcoefs;
16726 npaircomparisons = 0;
16727 }
16728 }
16729 /* free temporary memory */
16730 SCIPfreeBufferArray(scip, &usefulconss);
16731 }
16732 }
16733
16734 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16735 * in linear constraints and we therefore have full information about it
16736 */
16737 if( !cutoff && firstupgradetry < nconss
16738 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16739 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16740 )
16741 {
16742 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16743 {
16744 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds, nchgvartypes) );
16745 }
16746 }
16747
16748 /* try to upgrade constraints into a more specific constraint type;
16749 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16750 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16751 */
16752 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16753 {
16754 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16755 {
16756 cons = conss[c];
16757
16758 /* don't upgrade modifiable constraints */
16759 if( SCIPconsIsModifiable(cons) )
16760 continue;
16761
16762 consdata = SCIPconsGetData(cons);
16763 assert(consdata != NULL);
16764
16765 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16766 if( consdata->upgradetried )
16767 continue;
16768 /* @todo force that upgrade will be performed later? */
16769 if( !consdata->presolved )
16770 continue;
16771
16772 consdata->upgradetried = TRUE;
16773 if( SCIPconsIsActive(cons) )
16774 {
16775 SCIP_CONS* upgdcons;
16776
16777 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16778 if( upgdcons != NULL )
16779 {
16780 /* add the upgraded constraint to the problem */
16781 SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16782 SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16783 (*nupgdconss)++;
16784
16785 /* mark the linear constraint being upgraded and to be removed after presolving;
16786 * don't delete it directly, because it may help to preprocess other linear constraints
16787 */
16788 assert(!consdata->upgraded);
16789 consdata->upgraded = TRUE;
16790
16791 /* delete upgraded inequalities immediately;
16792 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16793 */
16794 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16795 || !conshdlrdata->presolpairwise
16796 || (conshdlrdata->maxaggrnormscale == 0.0) )
16797 {
16798 SCIP_CALL( SCIPdelCons(scip, cons) );
16799 }
16800 }
16801 }
16802 }
16803 }
16804
16805 /* return the correct result code */
16806 if( cutoff )
16807 *result = SCIP_CUTOFF;
16808 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16809 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16810 *result = SCIP_SUCCESS;
16811 else
16812 *result = SCIP_DIDNOTFIND;
16813
16814 return SCIP_OKAY;
16815}
16816
16817
16818/** propagation conflict resolving method of constraint handler */
16819static
16820SCIP_DECL_CONSRESPROP(consRespropLinear)
16821{ /*lint --e{715}*/
16822 assert(scip != NULL);
16823 assert(cons != NULL);
16824 assert(result != NULL);
16825
16826 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16827
16828 return SCIP_OKAY;
16829}
16830
16831
16832/** variable rounding lock method of constraint handler */
16833static
16834SCIP_DECL_CONSLOCK(consLockLinear)
16835{ /*lint --e{715}*/
16836 SCIP_CONSDATA* consdata;
16837 SCIP_Bool haslhs;
16838 SCIP_Bool hasrhs;
16839 int i;
16840
16841 assert(scip != NULL);
16842 assert(cons != NULL);
16843 consdata = SCIPconsGetData(cons);
16844 assert(consdata != NULL);
16845
16846 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16847 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16848
16849 /* update rounding locks of every single variable */
16850 for( i = 0; i < consdata->nvars; ++i )
16851 {
16852 if( SCIPisPositive(scip, consdata->vals[i]) )
16853 {
16854 if( haslhs )
16855 {
16856 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16857 }
16858 if( hasrhs )
16859 {
16860 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16861 }
16862 }
16863 else
16864 {
16865 if( haslhs )
16866 {
16867 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16868 }
16869 if( hasrhs )
16870 {
16871 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16872 }
16873 }
16874 }
16875
16876 return SCIP_OKAY;
16877}
16878
16879
16880/** variable deletion method of constraint handler */
16881static
16882SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16883{
16884 assert(scip != NULL);
16885 assert(conshdlr != NULL);
16886 assert(conss != NULL || nconss == 0);
16887
16888 if( nconss > 0 )
16889 {
16890 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16891 }
16892
16893 return SCIP_OKAY;
16894}
16895
16896/** constraint display method of constraint handler */
16897static
16898SCIP_DECL_CONSPRINT(consPrintLinear)
16899{ /*lint --e{715}*/
16900 assert(scip != NULL);
16901 assert(conshdlr != NULL);
16902 assert(cons != NULL);
16903
16905
16906 return SCIP_OKAY;
16907}
16908
16909/** constraint copying method of constraint handler */
16910static
16911SCIP_DECL_CONSCOPY(consCopyLinear)
16912{ /*lint --e{715}*/
16913 SCIP_VAR** sourcevars;
16914 SCIP_Real* sourcecoefs;
16915 const char* consname;
16916 int nvars;
16917
16918 assert(scip != NULL);
16919 assert(sourcescip != NULL);
16920 assert(sourcecons != NULL);
16921
16922 /* get variables and coefficients of the source constraint */
16923 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16924 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16925 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16926
16927 if( name != NULL )
16928 consname = name;
16929 else
16930 consname = SCIPconsGetName(sourcecons);
16931
16932 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16933 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16934 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16935 assert(cons != NULL || *valid == FALSE);
16936
16937 /* @todo should also the checkabsolute flag of the constraint be copied? */
16938
16939 return SCIP_OKAY;
16940}
16941
16942/** find operators '<=', '==', '>=', [free] in input string and return those places
16943 *
16944 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16945 */
16946static
16948 const char* str, /**< null terminated input string */
16949 char** firstoperator, /**< pointer to store the string starting at the first operator */
16950 char** secondoperator, /**< pointer to store the string starting at the second operator */
16951 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16952 )
16953{
16954 char* curr;
16955
16956 assert(str != NULL);
16957 assert(firstoperator != NULL);
16958 assert(secondoperator != NULL);
16959
16960 *firstoperator = NULL;
16961 *secondoperator = NULL;
16962
16963 curr = (char*)str;
16964 *success = TRUE;
16965
16966 /* loop over the input string to find all operators */
16967 while( *curr && *success )
16968 {
16969 SCIP_Bool found = FALSE;
16970 int increment = 1;
16971
16972 /* try if we found a possible operator */
16973 switch( *curr )
16974 {
16975 case '<':
16976 case '=':
16977 case '>':
16978
16979 /* check if the two characters curr[0,1] form an operator together */
16980 if( curr[1] == '=' )
16981 {
16982 found = TRUE;
16983
16984 /* update increment to continue after this operator */
16985 increment = 2;
16986 }
16987 break;
16988 case '[':
16989 if( strncmp(curr, "[free]", 6) == 0 )
16990 {
16991 found = TRUE;
16992
16993 /* update increment to continue after this operator */
16994 increment = 6;
16995 }
16996 break;
16997 default:
16998 break;
16999 }
17000
17001 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
17002 if( found )
17003 {
17004 if( *firstoperator == NULL )
17005 {
17006 *firstoperator = curr;
17007 }
17008 else
17009 {
17010 if( *secondoperator != NULL )
17011 {
17012 SCIPerrorMessage("Found more than two operators in line %s\n", str);
17013 *success = FALSE;
17014 }
17015 else if( strncmp(*firstoperator, "<=", 2) != 0 )
17016 {
17017 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17018 *success = FALSE;
17019 }
17020 else if( strncmp(curr, "<=", 2) != 0 )
17021 {
17022 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17023 *success = FALSE;
17024 }
17025
17026 *secondoperator = curr;
17027 }
17028 }
17029
17030 curr += increment;
17031 }
17032
17033 /* check if we did find at least one operator */
17034 if( *success )
17035 {
17036 if( *firstoperator == NULL )
17037 {
17038 SCIPerrorMessage("Could not find any operator in line %s\n", str);
17039 *success = FALSE;
17040 }
17041 }
17042}
17043
17044/** constraint parsing method of constraint handler */
17045static
17046SCIP_DECL_CONSPARSE(consParseLinear)
17047{ /*lint --e{715}*/
17048 SCIP_VAR** vars;
17049 SCIP_Real* coefs;
17050 int nvars;
17051 int coefssize;
17052 int requsize;
17053 SCIP_Real lhs;
17054 SCIP_Real rhs;
17055 char* endptr;
17056 char* firstop;
17057 char* secondop;
17058 SCIP_Bool operatorsuccess;
17059 char* lhsstrptr;
17060 char* rhsstrptr;
17061 char* varstrptr;
17062
17063 assert(scip != NULL);
17064 assert(success != NULL);
17065 assert(str != NULL);
17066 assert(name != NULL);
17067 assert(cons != NULL);
17068
17069 /* set left and right hand side to their default values */
17070 lhs = -SCIPinfinity(scip);
17071 rhs = SCIPinfinity(scip);
17072
17073 (*success) = FALSE;
17074
17075 /* return of string empty */
17076 if( !*str )
17077 return SCIP_OKAY;
17078
17079 /* ignore whitespace */
17080 SCIP_CALL( SCIPskipSpace((char**)&str) );
17081
17082 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17083 * and the special word [free]
17084 */
17085 findOperators(str, &firstop, &secondop, &operatorsuccess);
17086
17087 /* if the grammar is not valid for parsing a linear constraint, return */
17088 if( ! operatorsuccess )
17089 return SCIP_OKAY;
17090
17091 varstrptr = (char *)str;
17092 lhsstrptr = rhsstrptr = NULL;
17093 assert(firstop != NULL);
17094
17095 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17096 switch( *firstop )
17097 {
17098 case '<':
17099 assert(firstop[1] == '=');
17100 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17101 if( secondop != NULL )
17102 {
17103 assert(secondop[0] == '<' && secondop[1] == '=');
17104 lhsstrptr = (char *)str;
17105 varstrptr = firstop + 2;
17106 rhsstrptr = secondop + 2;
17107 }
17108 else
17109 {
17110 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17111 lhsstrptr = NULL;
17112 varstrptr = (char *)str;
17113 rhsstrptr = firstop + 2;
17114 }
17115 break;
17116 case '>':
17117 assert(firstop[1] == '=');
17118 assert(secondop == NULL);
17119 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17120 lhsstrptr = firstop + 2;
17121 break;
17122 case '=':
17123 assert(firstop[1] == '=');
17124 assert(secondop == NULL);
17125 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17126 rhsstrptr = firstop + 2;
17127 lhsstrptr = firstop + 2;
17128 break;
17129 case '[':
17130 assert(strncmp(firstop, "[free]", 6) == 0);
17131 assert(secondop == NULL);
17132 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17133 break;
17134 default:
17135 /* it should not be possible that a different character appears in that position */
17136 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17137 return SCIP_READERROR;
17138 }
17139
17140 /* parse left hand side, if necessary */
17141 if( lhsstrptr != NULL )
17142 {
17143 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17144 {
17145 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17146 return SCIP_OKAY;
17147 }
17148
17149 /* in case of an equation, assign the left also to the right hand side */
17150 if( rhsstrptr == lhsstrptr )
17151 rhs = lhs;
17152 }
17153
17154 /* parse right hand side, if different from left hand side */
17155 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17156 {
17157 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17158 {
17159 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17160 return SCIP_OKAY;
17161 }
17162 }
17163
17164 /* initialize buffers for storing the variables and coefficients */
17165 coefssize = 100;
17166 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17167 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17168
17169 assert(varstrptr != NULL);
17170
17171 /* parse linear sum to get variables and coefficients */
17172 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17173
17174 if( *success && requsize > coefssize )
17175 {
17176 /* realloc buffers and try again */
17177 coefssize = requsize;
17178 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17179 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17180
17181 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17182 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17183 }
17184
17185 if( !*success )
17186 {
17187 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17188 }
17189 else
17190 {
17191 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17192 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17193 }
17194
17195 SCIPfreeBufferArray(scip, &coefs);
17196 SCIPfreeBufferArray(scip, &vars);
17197
17198 return SCIP_OKAY;
17199}
17200
17201
17202/** constraint method of constraint handler which returns the variables (if possible) */
17203static
17204SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17205{ /*lint --e{715}*/
17206 SCIP_CONSDATA* consdata;
17207
17208 consdata = SCIPconsGetData(cons);
17209 assert(consdata != NULL);
17210
17211 if( varssize < consdata->nvars )
17212 (*success) = FALSE;
17213 else
17214 {
17215 assert(vars != NULL);
17216
17217 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17218 (*success) = TRUE;
17219 }
17220
17221 return SCIP_OKAY;
17222}
17223
17224/**! [Callback for the number of variables]*/
17225/** constraint method of constraint handler which returns the number of variables (if possible) */
17226static
17227SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17228{ /*lint --e{715}*/
17229 SCIP_CONSDATA* consdata;
17230
17231 consdata = SCIPconsGetData(cons);
17232 assert(consdata != NULL);
17233
17234 (*nvars) = consdata->nvars;
17235 (*success) = TRUE;
17236
17237 return SCIP_OKAY;
17238}
17239/**! [Callback for the number of variables]*/
17240
17241/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17242static
17243SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17244{ /*lint --e{715}*/
17245 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17246
17247 return SCIP_OKAY;
17248}
17249
17250/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17251static
17252SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17253{ /*lint --e{715}*/
17254 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17255
17256 return SCIP_OKAY;
17257}
17258
17259/*
17260 * Callback methods of event handler
17261 */
17262
17263/** execution method of event handler */
17264static
17265SCIP_DECL_EVENTEXEC(eventExecLinear)
17266{ /*lint --e{715}*/
17267 SCIP_CONS* cons;
17268 SCIP_CONSDATA* consdata;
17269 SCIP_VAR* var;
17270 SCIP_EVENTTYPE eventtype;
17271
17272 assert(scip != NULL);
17273 assert(eventhdlr != NULL);
17274 assert(eventdata != NULL);
17275 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17276 assert(event != NULL);
17277
17278 cons = eventdata->cons;
17279 assert(cons != NULL);
17280 consdata = SCIPconsGetData(cons);
17281 assert(consdata != NULL);
17282
17283 /* we can skip events droped for deleted constraints */
17284 if( SCIPconsIsDeleted(cons) )
17285 return SCIP_OKAY;
17286
17287 eventtype = SCIPeventGetType(event);
17288 var = SCIPeventGetVar(event);
17289
17290 if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17291 {
17292 SCIP_Real oldbound;
17293 SCIP_Real newbound;
17294 SCIP_Real val;
17295 int varpos;
17296
17297 varpos = eventdata->varpos;
17298 assert(0 <= varpos && varpos < consdata->nvars);
17299 oldbound = SCIPeventGetOldbound(event);
17300 newbound = SCIPeventGetNewbound(event);
17301 assert(var != NULL);
17302 assert(consdata->vars[varpos] == var);
17303 val = consdata->vals[varpos];
17304
17305 /* we only need to update the activities if the constraint is active,
17306 * otherwise we mark them to be invalid
17307 */
17308 if( SCIPconsIsActive(cons) )
17309 {
17310 /* update the activity values */
17311 if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17312 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17313 else
17314 {
17315 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17316 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17317 }
17318 }
17319 else
17321
17322 consdata->presolved = FALSE;
17323 consdata->rangedrowpropagated = 0;
17324
17325 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17326 if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17327 {
17329
17330 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17331 if( consdata->maxactdeltavar == var )
17332 {
17333 consdata->maxactdelta = SCIP_INVALID;
17334 consdata->maxactdeltavar = NULL;
17335 }
17336
17337 /* check whether bound tightening might now be successful */
17338 if( consdata->boundstightened > 0)
17339 {
17340 switch( eventtype )
17341 {
17343 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17344 consdata->boundstightened = 0;
17345 break;
17347 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17348 consdata->boundstightened = 0;
17349 break;
17350 default:
17351 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17352 return SCIP_INVALIDDATA;
17353 }
17354 }
17355 }
17356 /* update maximal activity delta if a bound was relaxed */
17357 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17358 {
17359 SCIP_Real lb;
17360 SCIP_Real ub;
17361 SCIP_Real domain;
17362 SCIP_Real delta;
17363
17364 assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17365
17366 lb = SCIPvarGetLbLocal(var);
17367 ub = SCIPvarGetUbLocal(var);
17368
17369 domain = ub - lb;
17370 delta = REALABS(val) * domain;
17371
17372 if( delta > consdata->maxactdelta )
17373 {
17374 consdata->maxactdelta = delta;
17375 consdata->maxactdeltavar = var;
17376 }
17377 }
17378 }
17379 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17380 {
17381 /* we want to remove the fixed variable */
17382 consdata->presolved = FALSE;
17383 consdata->removedfixings = FALSE;
17384 consdata->rangedrowpropagated = 0;
17385
17386 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17387 if( consdata->maxactdeltavar == var )
17388 {
17389 consdata->maxactdelta = SCIP_INVALID;
17390 consdata->maxactdeltavar = NULL;
17391 }
17392 }
17393 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17394 {
17395 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17398 consdata->presolved = FALSE;
17399 }
17400 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17401 {
17402 SCIP_Real oldbound;
17403 SCIP_Real newbound;
17404 SCIP_Real val;
17405 int varpos;
17406
17407 varpos = eventdata->varpos;
17408 assert(0 <= varpos && varpos < consdata->nvars);
17409 oldbound = SCIPeventGetOldbound(event);
17410 newbound = SCIPeventGetNewbound(event);
17411 assert(var != NULL);
17412 assert(consdata->vars[varpos] == var);
17413 val = consdata->vals[varpos];
17414
17415 consdata->rangedrowpropagated = 0;
17416
17417 /* update the activity values */
17418 if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17419 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17420 else
17421 {
17422 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17423 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17424 }
17425
17426 /* if the variable is binary but not fixed it had to become binary due to this global change */
17428 {
17430 consdata->indexsorted = FALSE;
17431 else
17432 consdata->coefsorted = FALSE;
17433 }
17434 }
17435 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17436 {
17438
17439 /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17440 consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17441
17442 /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17443 consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17444 }
17445 else
17446 {
17447 assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17448 consdata->varsdeleted = TRUE;
17449 }
17450
17451 return SCIP_OKAY;
17452}
17453
17454
17455/*
17456 * Callback methods of conflict handler
17457 */
17458
17459/** conflict processing method of conflict handler (called when conflict was found) */
17460static
17461SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17462{ /*lint --e{715}*/
17463 SCIP_VAR** vars;
17464 SCIP_Real* vals;
17465 SCIP_Real lhs;
17466 int i;
17467
17468 assert(scip != NULL);
17469 assert(conflicthdlr != NULL);
17470 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17471 assert(bdchginfos != NULL || nbdchginfos == 0);
17472 assert(result != NULL);
17473
17474 /* don't process already resolved conflicts */
17475 if( resolved )
17476 {
17477 *result = SCIP_DIDNOTRUN;
17478 return SCIP_OKAY;
17479 }
17480
17481 *result = SCIP_DIDNOTFIND;
17482
17483 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17484 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17485 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17486 lhs = 1.0;
17487 for( i = 0; i < nbdchginfos; ++i )
17488 {
17489 assert(bdchginfos != NULL);
17490
17491 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17492
17493 /* we can only treat binary variables */
17494 /**@todo extend linear conflict constraints to some non-binary cases */
17495 if( !SCIPvarIsBinary(vars[i]) )
17496 break;
17497
17498 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17499 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17500 vals[i] = 1.0;
17501 else
17502 {
17503 vals[i] = -1.0;
17504 lhs -= 1.0;
17505 }
17506 }
17507
17508 if( i == nbdchginfos )
17509 {
17510 SCIP_CONS* cons;
17511 SCIP_CONS* upgdcons;
17512 char consname[SCIP_MAXSTRLEN];
17513
17514 /* create a constraint out of the conflict set */
17516 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17517 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17518
17519 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17520 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17521 if( upgdcons != NULL )
17522 {
17523 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17524 cons = upgdcons;
17525 }
17526
17527 /* add conflict to SCIP */
17528 SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17529
17530 *result = SCIP_CONSADDED;
17531 }
17532
17533 /* free temporary memory */
17534 SCIPfreeBufferArray(scip, &vals);
17535 SCIPfreeBufferArray(scip, &vars);
17536
17537 return SCIP_OKAY;
17538}
17539
17540
17541/*
17542 * Nonlinear constraint upgrading
17543 */
17544
17545/** tries to upgrade a nonlinear constraint into a linear constraint */
17546static
17547SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17548{
17549 SCIP_CONSDATA* consdata;
17550 SCIP_EXPR* expr;
17551 SCIP_Real lhs;
17552 SCIP_Real rhs;
17553 int i;
17554
17555 assert(nupgdconss != NULL);
17556 assert(upgdconss != NULL);
17557 assert(upgdconsssize > 0);
17558
17559 expr = SCIPgetExprNonlinear(cons);
17560 assert(expr != NULL);
17561
17562 /* not a linear constraint if the expression is not a sum
17563 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17564 */
17565 if( !SCIPisExprSum(scip, expr) )
17566 return SCIP_OKAY;
17567
17568 /* if at least one child is not a variable, then not a linear constraint */
17569 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17570 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17571 return SCIP_OKAY;
17572
17573 /* consider constant part of the sum expression */
17576
17577 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17578 0, NULL, NULL, lhs, rhs,
17582 SCIPconsIsStickingAtNode(cons)) );
17583 assert(upgdconss[0] != NULL);
17584
17585 consdata = SCIPconsGetData(upgdconss[0]);
17586
17587 /* add linear terms */
17589 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17590 {
17592 }
17593
17594 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17595 consdata->checkabsolute = TRUE;
17596
17597 *nupgdconss = 1;
17598
17599 SCIPdebugMsg(scip, "created linear constraint:\n");
17600 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17601
17602 return SCIP_OKAY;
17603} /*lint !e715*/
17604
17605/*
17606 * constraint specific interface methods
17607 */
17608
17609/** creates the handler for linear constraints and includes it in SCIP */
17611 SCIP* scip /**< SCIP data structure */
17612 )
17613{
17614 SCIP_CONSHDLRDATA* conshdlrdata;
17615 SCIP_CONSHDLR* conshdlr;
17616 SCIP_EVENTHDLR* eventhdlr;
17617 SCIP_CONFLICTHDLR* conflicthdlr;
17618
17619 assert(scip != NULL);
17620
17621 /* create event handler for bound change events */
17623 eventExecLinear, NULL) );
17624
17625 /* create conflict handler for linear constraints */
17627 conflictExecLinear, NULL) );
17628
17629 /* create constraint handler data */
17630 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17631
17632 /* include constraint handler */
17635 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17636 conshdlrdata) );
17637
17638 assert(conshdlr != NULL);
17639
17640 /* set non-fundamental callbacks via specific setter functions */
17641 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17642 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17643 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17644 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17645 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17646 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17647 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17648 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17649 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17650 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17651 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17652 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17653 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17654 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17655 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17657 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17660 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17661 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17663 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17664 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17665 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17666 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17667
17668 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17669 {
17670 /* include the linear constraint upgrade in the nonlinear constraint handler */
17672 }
17673
17674 /* add linear constraint handler parameters */
17676 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17677 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17678 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17680 "constraints/" CONSHDLR_NAME "/maxrounds",
17681 "maximal number of separation rounds per node (-1: unlimited)",
17682 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17684 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17685 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17686 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17688 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17689 "maximal number of cuts separated per separation round",
17690 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17692 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17693 "maximal number of cuts separated per separation round in the root node",
17694 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17696 "constraints/" CONSHDLR_NAME "/presolpairwise",
17697 "should pairwise constraint comparison be performed in presolving?",
17698 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17700 "constraints/" CONSHDLR_NAME "/presolusehashing",
17701 "should hash table be used for detecting redundant constraints in advance",
17702 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17704 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17705 "number for minimal pairwise presolve comparisons",
17706 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17708 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17709 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17710 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17712 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17713 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17714 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17716 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17717 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17718 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17720 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17721 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17722 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17724 "constraints/" CONSHDLR_NAME "/separateall",
17725 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17726 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17728 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17729 "should presolving search for aggregations in equations",
17730 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17732 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17733 "should presolving try to simplify inequalities",
17734 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17736 "constraints/" CONSHDLR_NAME "/dualpresolving",
17737 "should dual presolving steps be performed?",
17738 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17740 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17741 "should stuffing of singleton continuous variables be performed?",
17742 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17744 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17745 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17746 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17748 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17749 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17751 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17752 "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)?",
17753 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17755 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17756 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17757 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17759 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17760 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17761 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17763 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17764 "should presolving try to detect subsets of constraints parallel to the objective function?",
17765 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17767 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17768 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17769 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17771 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17772 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17773 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17775 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17776 "maximum depth to apply ranged row propagation",
17777 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17779 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17780 "frequency for applying ranged row propagation",
17781 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17783 "constraints/" CONSHDLR_NAME "/multaggrremove",
17784 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17785 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17787 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17788 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17789 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17791 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17792 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17793 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17795 "constraints/" CONSHDLR_NAME "/extractcliques",
17796 "should Cliques be extracted?",
17797 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17798
17799 return SCIP_OKAY;
17800}
17801
17802/** includes a linear constraint update method into the linear constraint handler */
17804 SCIP* scip, /**< SCIP data structure */
17805 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17806 int priority, /**< priority of upgrading method */
17807 const char* conshdlrname /**< name of the constraint handler */
17808 )
17809{
17810 SCIP_CONSHDLR* conshdlr;
17811 SCIP_CONSHDLRDATA* conshdlrdata;
17812 SCIP_LINCONSUPGRADE* linconsupgrade;
17814 char paramdesc[SCIP_MAXSTRLEN];
17815
17816 assert(scip != NULL);
17817 assert(linconsupgd != NULL);
17818 assert(conshdlrname != NULL );
17819
17820 /* find the linear constraint handler */
17821 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17822 if( conshdlr == NULL )
17823 {
17824 SCIPerrorMessage("linear constraint handler not found\n");
17825 return SCIP_PLUGINNOTFOUND;
17826 }
17827
17828 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17829 assert(conshdlrdata != NULL);
17830
17831 /* check if linear constraint update method already exists in constraint handler data */
17832 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17833 {
17834 /* create a linear constraint upgrade data object */
17835 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17836
17837 /* insert linear constraint update method into constraint handler data */
17838 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17839
17840 /* adds parameter to turn on and off the upgrading step */
17841 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17842 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17844 paramname, paramdesc,
17845 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17846 }
17847
17848 return SCIP_OKAY;
17849}
17850
17851/** creates and captures a linear constraint
17852 *
17853 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17854 */
17856 SCIP* scip, /**< SCIP data structure */
17857 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17858 const char* name, /**< name of constraint */
17859 int nvars, /**< number of nonzeros in the constraint */
17860 SCIP_VAR** vars, /**< array with variables of constraint entries */
17861 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17862 SCIP_Real lhs, /**< left hand side of constraint */
17863 SCIP_Real rhs, /**< right hand side of constraint */
17864 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17865 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17866 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17867 * Usually set to TRUE. */
17868 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17869 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17870 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17871 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17872 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17873 * Usually set to TRUE. */
17874 SCIP_Bool local, /**< is constraint only valid locally?
17875 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17876 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17877 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17878 * adds coefficients to this constraint. */
17879 SCIP_Bool dynamic, /**< is constraint subject to aging?
17880 * Usually set to FALSE. Set to TRUE for own cuts which
17881 * are separated as constraints. */
17882 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17883 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17884 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17885 * if it may be moved to a more global node?
17886 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17887 )
17888{
17889 SCIP_CONSHDLR* conshdlr;
17890 SCIP_CONSDATA* consdata;
17891 int j;
17892
17893 assert(scip != NULL);
17894 assert(cons != NULL);
17895
17896 /* find the linear constraint handler */
17897 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17898 if( conshdlr == NULL )
17899 {
17900 SCIPerrorMessage("linear constraint handler not found\n");
17901 return SCIP_PLUGINNOTFOUND;
17902 }
17903
17904 for( j = 0; j < nvars; ++j )
17905 {
17906 if( SCIPisInfinity(scip, REALABS(vals[j])) )
17907 {
17908 SCIPerrorMessage("coefficient of variable <%s> is infinite.\n", SCIPvarGetName(vars[j]));
17909 SCIPABORT();
17910 return SCIP_INVALIDDATA;
17911 }
17912 }
17913
17914 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17915 * constraint after presolving we have to ensure that it holds active variables
17916 */
17917 if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17918 {
17919 SCIP_VAR** consvars;
17920 SCIP_Real* consvals;
17921 SCIP_Real constant = 0.0;
17922 int nconsvars;
17923 int requiredsize;
17924
17925 nconsvars = nvars;
17926 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17927 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17928
17929 /* get active variables for new constraint */
17930 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17931
17932 /* if space was not enough we need to resize the buffers */
17933 if( requiredsize > nconsvars )
17934 {
17935 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17936 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17937
17938 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17939 assert(requiredsize <= nconsvars);
17940 }
17941
17942 /* adjust sides and check that we do not subtract infinity values */
17943 if( SCIPisInfinity(scip, REALABS(constant)) )
17944 {
17945 if( constant < 0.0 )
17946 {
17947 if( SCIPisInfinity(scip, lhs) )
17948 {
17949 SCIPfreeBufferArray(scip, &consvals);
17950 SCIPfreeBufferArray(scip, &consvars);
17951
17952 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);
17953
17954 SCIPABORT();
17955 return SCIP_INVALIDDATA; /*lint !e527*/
17956 }
17957 if( SCIPisInfinity(scip, rhs) )
17958 {
17959 SCIPfreeBufferArray(scip, &consvals);
17960 SCIPfreeBufferArray(scip, &consvars);
17961
17962 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);
17963
17964 SCIPABORT();
17965 return SCIP_INVALIDDATA; /*lint !e527*/
17966 }
17967
17968 lhs = -SCIPinfinity(scip);
17969 rhs = -SCIPinfinity(scip);
17970 }
17971 else
17972 {
17973 if( SCIPisInfinity(scip, -lhs) )
17974 {
17975 SCIPfreeBufferArray(scip, &consvals);
17976 SCIPfreeBufferArray(scip, &consvars);
17977
17978 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);
17979
17980 SCIPABORT();
17981 return SCIP_INVALIDDATA; /*lint !e527*/
17982 }
17983 if( SCIPisInfinity(scip, -rhs) )
17984 {
17985 SCIPfreeBufferArray(scip, &consvals);
17986 SCIPfreeBufferArray(scip, &consvars);
17987
17988 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);
17989
17990 SCIPABORT();
17991 return SCIP_INVALIDDATA; /*lint !e527*/
17992 }
17993
17994 lhs = SCIPinfinity(scip);
17995 rhs = SCIPinfinity(scip);
17996 }
17997 }
17998 else
17999 {
18000 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18001 lhs -= constant;
18002 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18003 rhs -= constant;
18004
18005 if( SCIPisInfinity(scip, -lhs) )
18006 lhs = -SCIPinfinity(scip);
18007 else if( SCIPisInfinity(scip, lhs) )
18008 lhs = SCIPinfinity(scip);
18009
18010 if( SCIPisInfinity(scip, rhs) )
18011 rhs = SCIPinfinity(scip);
18012 else if( SCIPisInfinity(scip, -rhs) )
18013 rhs = -SCIPinfinity(scip);
18014 }
18015
18016 /* create constraint data */
18017 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
18018 assert(consdata != NULL);
18019
18020 SCIPfreeBufferArray(scip, &consvals);
18021 SCIPfreeBufferArray(scip, &consvars);
18022 }
18023 else
18024 {
18025 /* create constraint data */
18026 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18027 assert(consdata != NULL);
18028 }
18029
18030#ifndef NDEBUG
18031 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18032 if( check || enforce )
18033 {
18034 int n;
18035 for(n = consdata->nvars - 1; n >= 0; --n )
18036 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18037 }
18038#endif
18039
18040 /* create constraint */
18041 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18042 local, modifiable, dynamic, removable, stickingatnode) );
18043
18044 return SCIP_OKAY;
18045}
18046
18047/** creates and captures a linear constraint
18048 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18049 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18050 *
18051 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18052 *
18053 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18054 */
18056 SCIP* scip, /**< SCIP data structure */
18057 SCIP_CONS** cons, /**< pointer to hold the created constraint */
18058 const char* name, /**< name of constraint */
18059 int nvars, /**< number of nonzeros in the constraint */
18060 SCIP_VAR** vars, /**< array with variables of constraint entries */
18061 SCIP_Real* vals, /**< array with coefficients of constraint entries */
18062 SCIP_Real lhs, /**< left hand side of constraint */
18063 SCIP_Real rhs /**< right hand side of constraint */
18064 )
18065{
18066 assert(scip != NULL);
18067
18068 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18070
18071 return SCIP_OKAY;
18072}
18073
18074/** creates by copying and captures a linear constraint */
18076 SCIP* scip, /**< target SCIP data structure */
18077 SCIP_CONS** cons, /**< pointer to store the created target constraint */
18078 SCIP* sourcescip, /**< source SCIP data structure */
18079 const char* name, /**< name of constraint */
18080 int nvars, /**< number of variables in source variable array */
18081 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18082 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18083 SCIP_Real lhs, /**< left hand side of the linear constraint */
18084 SCIP_Real rhs, /**< right hand side of the linear constraint */
18085 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18086 * variables of the target SCIP */
18087 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18088 * target constraints */
18089 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18090 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18091 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18092 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18093 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18094 SCIP_Bool local, /**< is constraint only valid locally? */
18095 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18096 SCIP_Bool dynamic, /**< is constraint subject to aging? */
18097 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18098 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18099 * if it may be moved to a more global node? */
18100 SCIP_Bool global, /**< create a global or a local copy? */
18101 SCIP_Bool* valid /**< pointer to store if the copying was valid */
18102 )
18103{
18104 SCIP_VAR** vars;
18105 SCIP_Real* coefs;
18106
18107 SCIP_Real constant;
18108 int requiredsize;
18109 int v;
18110 SCIP_Bool success;
18111
18112 if( SCIPisGT(scip, lhs, rhs) )
18113 {
18114 *valid = FALSE;
18115 return SCIP_OKAY;
18116 }
18117
18118 (*valid) = TRUE;
18119
18120 if( nvars == 0 )
18121 {
18122 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18123 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18124 return SCIP_OKAY;
18125 }
18126
18127 /* duplicate variable array */
18128 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
18129
18130 /* duplicate coefficient array */
18131 if( sourcecoefs != NULL )
18132 {
18133 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18134 }
18135 else
18136 {
18137 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18138 for( v = 0; v < nvars; ++v )
18139 coefs[v] = 1.0;
18140 }
18141
18142 constant = 0.0;
18143
18144 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18145 * the target SCIP
18146 */
18147 if( !SCIPvarIsOriginal(vars[0]) )
18148 {
18149 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18150
18151 if( requiredsize > nvars )
18152 {
18153 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18154 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18155
18156 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18157 assert(requiredsize <= nvars);
18158 }
18159 }
18160 else
18161 {
18162 for( v = 0; v < nvars; ++v )
18163 {
18164 assert(SCIPvarIsOriginal(vars[v]));
18165 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18166 assert(vars[v] != NULL);
18167 }
18168 }
18169
18170 success = TRUE;
18171 /* map variables of the source constraint to variables of the target SCIP */
18172 for( v = 0; v < nvars && success; ++v )
18173 {
18174 SCIP_VAR* var;
18175 var = vars[v];
18176
18177 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18178 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18179
18180 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18181 assert(!(success) || vars[v] != NULL);
18182 }
18183
18184 /* only create the target constraint, if all variables could be copied */
18185 if( success )
18186 {
18187 if( !SCIPisInfinity(scip, -lhs) )
18188 lhs -= constant;
18189
18190 if( !SCIPisInfinity(scip, rhs) )
18191 rhs -= constant;
18192
18193 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18194 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18195 }
18196 else
18197 *valid = FALSE;
18198
18199 /* free buffer array */
18200 SCIPfreeBufferArray(scip, &coefs);
18201 SCIPfreeBufferArray(scip, &vars);
18202
18203 return SCIP_OKAY;
18204}
18205
18206/** adds coefficient to linear constraint (if it is not zero) */
18208 SCIP* scip, /**< SCIP data structure */
18209 SCIP_CONS* cons, /**< constraint data */
18210 SCIP_VAR* var, /**< variable of constraint entry */
18211 SCIP_Real val /**< coefficient of constraint entry */
18212 )
18213{
18214 assert(scip != NULL);
18215 assert(cons != NULL);
18216 assert(var != NULL);
18217
18218 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18219 {
18220 SCIPerrorMessage("constraint is not linear\n");
18221 return SCIP_INVALIDDATA;
18222 }
18223
18224 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18225 * constraint after presolving we have to ensure that it holds active variables
18226 */
18228 {
18229 SCIP_CONSDATA* consdata;
18230 SCIP_VAR** consvars;
18231 SCIP_Real* consvals;
18232 SCIP_Real constant = 0.0;
18233 SCIP_Real rhs;
18234 SCIP_Real lhs;
18235 int nconsvars;
18236 int requiredsize;
18237 int v;
18238
18239 nconsvars = 1;
18240 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18241 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18242 consvars[0] = var;
18243 consvals[0] = val;
18244
18245 /* get active variables for new constraint */
18246 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18247
18248 /* if space was not enough we need to resize the buffers */
18249 if( requiredsize > nconsvars )
18250 {
18251 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18252 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18253
18254 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18255 assert(requiredsize <= nconsvars);
18256 }
18257
18258 consdata = SCIPconsGetData(cons);
18259 assert(consdata != NULL);
18260
18261 lhs = consdata->lhs;
18262 rhs = consdata->rhs;
18263
18264 /* adjust sides and check that we do not subtract infinity values */
18265 /* constant is infinite */
18266 if( SCIPisInfinity(scip, REALABS(constant)) )
18267 {
18268 if( constant < 0.0 )
18269 {
18270 if( SCIPisInfinity(scip, lhs) )
18271 {
18272 SCIPfreeBufferArray(scip, &consvals);
18273 SCIPfreeBufferArray(scip, &consvars);
18274
18275 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));
18276
18277 SCIPABORT();
18278 return SCIP_INVALIDDATA; /*lint !e527*/
18279 }
18280 if( SCIPisInfinity(scip, rhs) )
18281 {
18282 SCIPfreeBufferArray(scip, &consvals);
18283 SCIPfreeBufferArray(scip, &consvars);
18284
18285 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));
18286
18287 SCIPABORT();
18288 return SCIP_INVALIDDATA; /*lint !e527*/
18289 }
18290
18291 lhs = -SCIPinfinity(scip);
18292 rhs = -SCIPinfinity(scip);
18293 }
18294 else
18295 {
18296 if( SCIPisInfinity(scip, -lhs) )
18297 {
18298 SCIPfreeBufferArray(scip, &consvals);
18299 SCIPfreeBufferArray(scip, &consvars);
18300
18301 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));
18302
18303 SCIPABORT();
18304 return SCIP_INVALIDDATA; /*lint !e527*/
18305 }
18306 if( SCIPisInfinity(scip, -rhs) )
18307 {
18308 SCIPfreeBufferArray(scip, &consvals);
18309 SCIPfreeBufferArray(scip, &consvars);
18310
18311 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));
18312
18313 SCIPABORT();
18314 return SCIP_INVALIDDATA; /*lint !e527*/
18315 }
18316
18317 lhs = SCIPinfinity(scip);
18318 rhs = SCIPinfinity(scip);
18319 }
18320 }
18321 /* constant is not infinite */
18322 else
18323 {
18324 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18325 lhs -= constant;
18326 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18327 rhs -= constant;
18328
18329 if( SCIPisInfinity(scip, -lhs) )
18330 lhs = -SCIPinfinity(scip);
18331 else if( SCIPisInfinity(scip, lhs) )
18332 lhs = SCIPinfinity(scip);
18333
18334 if( SCIPisInfinity(scip, rhs) )
18335 rhs = SCIPinfinity(scip);
18336 else if( SCIPisInfinity(scip, -rhs) )
18337 rhs = -SCIPinfinity(scip);
18338 }
18339
18340 /* add all active variables to constraint */
18341 for( v = nconsvars - 1; v >= 0; --v )
18342 {
18343 if( !SCIPisZero(scip, consvals[v]) )
18344 {
18345 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18346 }
18347 }
18348
18349 /* update left and right hand sides */
18350 SCIP_CALL( chgLhs(scip, cons, lhs));
18351 SCIP_CALL( chgRhs(scip, cons, rhs));
18352
18353 SCIPfreeBufferArray(scip, &consvals);
18354 SCIPfreeBufferArray(scip, &consvars);
18355 }
18356 else if( !SCIPisZero(scip, val) )
18357 {
18358 SCIP_CALL( addCoef(scip, cons, var, val) );
18359 }
18360
18361 return SCIP_OKAY;
18362}
18363
18364/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18365 * not yet contained in the constraint
18366 *
18367 * @note This method may only be called during problem creation stage for an original constraint and variable.
18368 *
18369 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18370 */
18372 SCIP* scip, /**< SCIP data structure */
18373 SCIP_CONS* cons, /**< constraint data */
18374 SCIP_VAR* var, /**< variable of constraint entry */
18375 SCIP_Real val /**< new coefficient of constraint entry */
18376 )
18377{
18378 SCIP_CONSDATA* consdata;
18379 SCIP_VAR** vars;
18380 SCIP_Bool found;
18381 int i;
18382
18383 assert(scip != NULL);
18384 assert(cons != NULL);
18385 assert(var != NULL);
18386
18387 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18388 {
18389 SCIPerrorMessage("constraint is not linear\n");
18390 return SCIP_INVALIDDATA;
18391 }
18392
18394 {
18395 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18396 return SCIP_INVALIDDATA;
18397 }
18398
18399 consdata = SCIPconsGetData(cons);
18400 assert(consdata != NULL);
18401
18402 vars = consdata->vars;
18403 found = FALSE;
18404 i = 0;
18405 while( i < consdata->nvars )
18406 {
18407 if( vars[i] == var )
18408 {
18409 if( found || SCIPisZero(scip, val) )
18410 {
18411 SCIP_CALL( delCoefPos(scip, cons, i) );
18412
18413 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18414 i--;
18415 }
18416 else
18417 {
18418 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18419 }
18420 found = TRUE;
18421 }
18422 i++;
18423 }
18424
18425 if( !found )
18426 {
18427 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18428 }
18429
18430 return SCIP_OKAY;
18431}
18432
18433/** deletes variable from linear constraint
18434 *
18435 * @note This method may only be called during problem creation stage for an original constraint and variable.
18436 *
18437 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18438 */
18440 SCIP* scip, /**< SCIP data structure */
18441 SCIP_CONS* cons, /**< constraint data */
18442 SCIP_VAR* var /**< variable of constraint entry */
18443 )
18444{
18445 assert(scip != NULL);
18446 assert(cons != NULL);
18447 assert(var != NULL);
18448
18449 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18450
18451 return SCIP_OKAY;
18452}
18453
18454/** gets left hand side of linear constraint */
18456 SCIP* scip, /**< SCIP data structure */
18457 SCIP_CONS* cons /**< constraint data */
18458 )
18459{
18460 SCIP_CONSDATA* consdata;
18461
18462 assert(scip != NULL);
18463 assert(cons != NULL);
18464
18465 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18466 {
18467 SCIPerrorMessage("constraint is not linear\n");
18468 SCIPABORT();
18469 return SCIP_INVALID; /*lint !e527*/
18470 }
18471
18472 consdata = SCIPconsGetData(cons);
18473 assert(consdata != NULL);
18474
18475 return consdata->lhs;
18476}
18477
18478/** gets right hand side of linear constraint */
18480 SCIP* scip, /**< SCIP data structure */
18481 SCIP_CONS* cons /**< constraint data */
18482 )
18483{
18484 SCIP_CONSDATA* consdata;
18485
18486 assert(scip != NULL);
18487 assert(cons != NULL);
18488
18489 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18490 {
18491 SCIPerrorMessage("constraint is not linear\n");
18492 SCIPABORT();
18493 return SCIP_INVALID; /*lint !e527*/
18494 }
18495
18496 consdata = SCIPconsGetData(cons);
18497 assert(consdata != NULL);
18498
18499 return consdata->rhs;
18500}
18501
18502/** changes left hand side of linear constraint */
18504 SCIP* scip, /**< SCIP data structure */
18505 SCIP_CONS* cons, /**< constraint data */
18506 SCIP_Real lhs /**< new left hand side */
18507 )
18508{
18509 assert(scip != NULL);
18510 assert(cons != NULL);
18511
18512 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18513 {
18514 SCIPerrorMessage("constraint is not linear\n");
18515 return SCIP_INVALIDDATA;
18516 }
18517
18518 SCIP_CALL( chgLhs(scip, cons, lhs) );
18519
18520 return SCIP_OKAY;
18521}
18522
18523/** changes right hand side of linear constraint */
18525 SCIP* scip, /**< SCIP data structure */
18526 SCIP_CONS* cons, /**< constraint data */
18527 SCIP_Real rhs /**< new right hand side */
18528 )
18529{
18530 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18531 {
18532 SCIPerrorMessage("constraint is not linear\n");
18533 return SCIP_INVALIDDATA;
18534 }
18535
18536 SCIP_CALL( chgRhs(scip, cons, rhs) );
18537
18538 return SCIP_OKAY;
18539}
18540
18541/** gets the number of variables in the linear constraint */
18543 SCIP* scip, /**< SCIP data structure */
18544 SCIP_CONS* cons /**< constraint data */
18545 )
18546{
18547 SCIP_CONSDATA* consdata;
18548
18549 assert(scip != NULL);
18550 assert(cons != NULL);
18551
18552 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18553 {
18554 SCIPerrorMessage("constraint is not linear\n");
18555 SCIPABORT();
18556 return -1; /*lint !e527*/
18557 }
18558
18559 consdata = SCIPconsGetData(cons);
18560 assert(consdata != NULL);
18561
18562 return consdata->nvars;
18563}
18564
18565/** gets the array of variables in the linear constraint; the user must not modify this array! */
18567 SCIP* scip, /**< SCIP data structure */
18568 SCIP_CONS* cons /**< constraint data */
18569 )
18570{
18571 SCIP_CONSDATA* consdata;
18572
18573 assert(scip != NULL);
18574 assert(cons != NULL);
18575
18576 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18577 {
18578 SCIPerrorMessage("constraint is not linear\n");
18579 SCIPABORT();
18580 return NULL; /*lint !e527*/
18581 }
18582
18583 consdata = SCIPconsGetData(cons);
18584 assert(consdata != NULL);
18585
18586 return consdata->vars;
18587}
18588
18589/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18591 SCIP* scip, /**< SCIP data structure */
18592 SCIP_CONS* cons /**< constraint data */
18593 )
18594{
18595 SCIP_CONSDATA* consdata;
18596
18597 assert(scip != NULL);
18598 assert(cons != NULL);
18599
18600 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18601 {
18602 SCIPerrorMessage("constraint is not linear\n");
18603 SCIPABORT();
18604 return NULL; /*lint !e527*/
18605 }
18606
18607 consdata = SCIPconsGetData(cons);
18608 assert(consdata != NULL);
18609
18610 return consdata->vals;
18611}
18612
18613/** gets the activity of the linear constraint in the given solution
18614 *
18615 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18616 * comprises positive and negative infinity contributions
18617 */
18619 SCIP* scip, /**< SCIP data structure */
18620 SCIP_CONS* cons, /**< constraint data */
18621 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18622 )
18623{
18624 SCIP_CONSDATA* consdata;
18625
18626 assert(scip != NULL);
18627 assert(cons != NULL);
18628
18629 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18630 {
18631 SCIPerrorMessage("constraint is not linear\n");
18632 SCIPABORT();
18633 return SCIP_INVALID; /*lint !e527*/
18634 }
18635
18636 consdata = SCIPconsGetData(cons);
18637 assert(consdata != NULL);
18638
18639 if( consdata->row != NULL )
18640 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18641 else
18642 return consdataGetActivity(scip, consdata, sol);
18643}
18644
18645/** gets the feasibility of the linear constraint in the given solution */
18647 SCIP* scip, /**< SCIP data structure */
18648 SCIP_CONS* cons, /**< constraint data */
18649 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18650 )
18651{
18652 SCIP_CONSDATA* consdata;
18653
18654 assert(scip != NULL);
18655 assert(cons != NULL);
18656
18657 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18658 {
18659 SCIPerrorMessage("constraint is not linear\n");
18660 SCIPABORT();
18661 return SCIP_INVALID; /*lint !e527*/
18662 }
18663
18664 consdata = SCIPconsGetData(cons);
18665 assert(consdata != NULL);
18666
18667 if( consdata->row != NULL )
18668 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18669 else
18670 return consdataGetFeasibility(scip, consdata, sol);
18671}
18672
18673/** gets the dual solution of the linear constraint in the current LP */
18675 SCIP* scip, /**< SCIP data structure */
18676 SCIP_CONS* cons /**< constraint data */
18677 )
18678{
18679 SCIP_CONSDATA* consdata;
18680
18681 assert(scip != NULL);
18682 assert(cons != NULL);
18683 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18684
18685 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18686 {
18687 SCIPerrorMessage("constraint is not linear\n");
18688 SCIPABORT();
18689 return SCIP_INVALID; /*lint !e527*/
18690 }
18691
18692 consdata = SCIPconsGetData(cons);
18693 assert(consdata != NULL);
18694
18695 if( consdata->row != NULL )
18696 return SCIProwGetDualsol(consdata->row);
18697 else
18698 return 0.0;
18699}
18700
18701/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18703 SCIP* scip, /**< SCIP data structure */
18704 SCIP_CONS* cons /**< constraint data */
18705 )
18706{
18707 SCIP_CONSDATA* consdata;
18708
18709 assert(scip != NULL);
18710 assert(cons != NULL);
18711 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18712
18713 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18714 {
18715 SCIPerrorMessage("constraint is not linear\n");
18716 SCIPABORT();
18717 return SCIP_INVALID; /*lint !e527*/
18718 }
18719
18720 consdata = SCIPconsGetData(cons);
18721 assert(consdata != NULL);
18722
18723 if( consdata->row != NULL )
18724 return SCIProwGetDualfarkas(consdata->row);
18725 else
18726 return 0.0;
18727}
18728
18729/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18730 * the user must not modify the row!
18731 */
18733 SCIP* scip, /**< SCIP data structure */
18734 SCIP_CONS* cons /**< constraint data */
18735 )
18736{
18737 SCIP_CONSDATA* consdata;
18738
18739 assert(scip != NULL);
18740 assert(cons != NULL);
18741
18742 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18743 {
18744 SCIPerrorMessage("constraint is not linear\n");
18745 SCIPABORT();
18746 return NULL; /*lint !e527*/
18747 }
18748
18749 consdata = SCIPconsGetData(cons);
18750 assert(consdata != NULL);
18751
18752 return consdata->row;
18753}
18754
18755/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18757 SCIP* scip, /**< SCIP data structure */
18758 SCIP_CONS* cons, /**< source constraint to try to convert */
18759 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18760 )
18761{
18762 SCIP_CONSHDLR* conshdlr;
18763 SCIP_CONSHDLRDATA* conshdlrdata;
18764 SCIP_CONSDATA* consdata;
18765 SCIP_VAR* var;
18766 SCIP_Real val;
18767 SCIP_Real lb;
18768 SCIP_Real ub;
18769 SCIP_Real poscoeffsum;
18770 SCIP_Real negcoeffsum;
18771 SCIP_Bool infeasible;
18772 SCIP_Bool integral;
18773 int nchgsides = 0;
18774 int nposbin;
18775 int nnegbin;
18776 int nposint;
18777 int nnegint;
18778 int nposimpl;
18779 int nnegimpl;
18780 int nposimplbin;
18781 int nnegimplbin;
18782 int nposcont;
18783 int nnegcont;
18784 int ncoeffspone;
18785 int ncoeffsnone;
18786 int ncoeffspint;
18787 int ncoeffsnint;
18788 int ncoeffspfrac;
18789 int ncoeffsnfrac;
18790 int i;
18791
18792 assert(scip != NULL);
18793 assert(cons != NULL);
18794 assert(upgdcons != NULL);
18795
18796 *upgdcons = NULL;
18797
18798 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18799 if( SCIPconsIsModifiable(cons) )
18800 return SCIP_OKAY;
18801
18802 /* check for upgradability */
18803 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18804 return SCIP_OKAY;
18805
18806 /* get the constraint handler and check, if it's really a linear constraint */
18807 conshdlr = SCIPconsGetHdlr(cons);
18808 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18809 {
18810 SCIPerrorMessage("constraint is not linear\n");
18811 return SCIP_INVALIDDATA;
18812 }
18813
18814 /* get constraint handler data and constraint data */
18815 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18816 assert(conshdlrdata != NULL);
18817 consdata = SCIPconsGetData(cons);
18818 assert(consdata != NULL);
18819
18820 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18821 if( consdata->upgraded )
18822 return SCIP_OKAY;
18823
18824 /* check, if the constraint is already stored as LP row */
18825 if( consdata->row != NULL )
18826 {
18827 if( SCIProwIsInLP(consdata->row) )
18828 {
18829 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18830 return SCIP_INVALIDDATA;
18831 }
18832 else
18833 {
18834 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18835 }
18836 }
18837
18838 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18839
18840 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18841 * skipped and we hope that the infeasibility gets detected later again.
18842 *
18843 * TODO: do we want to try to upgrade the constraint anyway?
18844 *
18845 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18846 * proven to be infeasible.
18847 */
18848 if( infeasible ) /*lint !e774*/
18849 return SCIP_OKAY;
18850
18851 /* tighten sides */
18852 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18853
18854 if( infeasible ) /*lint !e774*/
18855 return SCIP_OKAY;
18856
18857 /*
18858 * calculate some statistics on linear constraint
18859 */
18860
18861 nposbin = 0;
18862 nnegbin = 0;
18863 nposint = 0;
18864 nnegint = 0;
18865 nposimpl = 0;
18866 nnegimpl = 0;
18867 nposimplbin = 0;
18868 nnegimplbin = 0;
18869 nposcont = 0;
18870 nnegcont = 0;
18871 ncoeffspone = 0;
18872 ncoeffsnone = 0;
18873 ncoeffspint = 0;
18874 ncoeffsnint = 0;
18875 ncoeffspfrac = 0;
18876 ncoeffsnfrac = 0;
18877 integral = TRUE;
18878 poscoeffsum = 0.0;
18879 negcoeffsum = 0.0;
18880
18881 for( i = 0; i < consdata->nvars; ++i )
18882 {
18883 var = consdata->vars[i];
18884 val = consdata->vals[i];
18885 lb = SCIPvarGetLbLocal(var);
18886 ub = SCIPvarGetUbLocal(var);
18887 assert(!SCIPisZero(scip, val));
18888
18889 switch( SCIPvarGetType(var) )
18890 {
18892 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18893 integral = integral && SCIPisIntegral(scip, val);
18894 if( val >= 0.0 )
18895 nposbin++;
18896 else
18897 nnegbin++;
18898 break;
18900 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18901 integral = integral && SCIPisIntegral(scip, val);
18902 if( val >= 0.0 )
18903 nposint++;
18904 else
18905 nnegint++;
18906 break;
18908 if( SCIPvarIsBinary(var) )
18909 {
18910 if( val >= 0.0 )
18911 nposimplbin++;
18912 else
18913 nnegimplbin++;
18914 }
18915 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18916 integral = integral && SCIPisIntegral(scip, val);
18917 if( val >= 0.0 )
18918 nposimpl++;
18919 else
18920 nnegimpl++;
18921 break;
18923 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18924 if( val >= 0.0 )
18925 nposcont++;
18926 else
18927 nnegcont++;
18928 break;
18929 default:
18930 SCIPerrorMessage("unknown variable type\n");
18931 return SCIP_INVALIDDATA;
18932 }
18933 if( SCIPisEQ(scip, val, 1.0) )
18934 ncoeffspone++;
18935 else if( SCIPisEQ(scip, val, -1.0) )
18936 ncoeffsnone++;
18937 else if( SCIPisIntegral(scip, val) )
18938 {
18939 if( SCIPisPositive(scip, val) )
18940 ncoeffspint++;
18941 else
18942 ncoeffsnint++;
18943 }
18944 else
18945 {
18946 if( SCIPisPositive(scip, val) )
18947 ncoeffspfrac++;
18948 else
18949 ncoeffsnfrac++;
18950 }
18951 if( SCIPisPositive(scip, val) )
18952 poscoeffsum += val;
18953 else
18954 negcoeffsum += val;
18955 }
18956
18957 /*
18958 * call the upgrading methods
18959 */
18960
18961 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18962 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18963 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",
18964 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18965 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18966 poscoeffsum, negcoeffsum, integral);
18967
18968 /* try all upgrading methods in priority order in case the upgrading step is enable */
18969 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18970 {
18971 if( conshdlrdata->linconsupgrades[i]->active )
18972 {
18973 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18974 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18975 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18976 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18977 poscoeffsum, negcoeffsum, integral,
18978 upgdcons) );
18979 }
18980 }
18981
18982#ifdef SCIP_DEBUG
18983 if( *upgdcons != NULL )
18984 {
18986 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18987 SCIPdebugPrintCons(scip, *upgdcons, NULL);
18988 }
18989#endif
18990
18991 return SCIP_OKAY; /*lint !e438*/
18992}
18993
18994/** cleans up (multi-)aggregations and fixings from linear constraints */
18996 SCIP* scip, /**< SCIP data structure */
18997 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18998 SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
18999 )
19000{
19001 SCIP_CONSHDLR* conshdlr;
19002 SCIP_CONS** conss;
19003 int nconss;
19004 int i;
19005
19006 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
19007 if( conshdlr == NULL )
19008 return SCIP_OKAY;
19009
19010 assert(infeasible != NULL);
19011 *infeasible = FALSE;
19012
19013 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
19014 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
19015
19016 for( i = 0; i < nconss; ++i )
19017 {
19018 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
19019
19020 if( *infeasible )
19021 break;
19022 }
19023
19024 return SCIP_OKAY;
19025}
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:7873
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:7184
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7468
#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:7940
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:7444
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:9508
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:9620
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:8910
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:7567
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:7006
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:9032
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:7657
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:7805
#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:7531
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:9566
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9452
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:7002
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:267
#define SCIP_MAXSTRLEN
Definition: def.h:288
#define COPYSIGN
Definition: def.h:258
#define SCIP_Longint
Definition: def.h:158
#define SCIP_MAXTREEDEPTH
Definition: def.h:316
#define SCIP_REAL_MAX
Definition: def.h:174
#define SCIP_INVALID
Definition: def.h:193
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:243
#define MAX3(x, y, z)
Definition: def.h:247
#define SCIP_Real
Definition: def.h:173
#define ABS(x)
Definition: def.h:235
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:239
#define SCIP_CALL_ABORT(x)
Definition: def.h:353
#define SCIP_LONGINT_FORMAT
Definition: def.h:165
#define MIN3(x, y, z)
Definition: def.h:251
#define SCIPABORT()
Definition: def.h:346
#define REALABS(x)
Definition: def.h:197
#define EPSGT(x, y, eps)
Definition: def.h:201
#define SCIP_CALL(x)
Definition: def.h:374
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:596
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip_general.c:633
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:724
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:380
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:3088
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:3042
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:2346
#define SCIPhashFour(a, b, c, d)
Definition: pub_misc.h:556
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2579
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2296
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2608
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2804
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2677
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2547
#define SCIPhashSignature64(a)
Definition: pub_misc.h:549
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip_prob.c:3696
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3474
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:3585
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3228
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3393
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:9121
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9373
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9394
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9824
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11184
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:10396
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:1217
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:141
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_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)
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:670
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17620
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:5203
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12774
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17640
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17915
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4351
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17882
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18190
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17894
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17748
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17599
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:6921
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:17538
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3353
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17834
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip_var.c:8565
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18144
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8598
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17561
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:8401
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:5615
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17926
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17822
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5320
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17584
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:18088
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17758
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4259
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4437
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:17768
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17419
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:8535
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18680
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:4645
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:4613
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17610
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8176
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1693
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17858
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17846
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:6780
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17630
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18134
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17574
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17706
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17904
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:17548
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18078
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8276
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:5501
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:11942
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:4513
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:18670
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:8629
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:5432
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17870
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17810
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:5538
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10877
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10866
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