SCIP Doxygen Documentation
 
Loading...
Searching...
No Matches
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( SCIPisPositive(scip, val) )
669 {
671 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
672 }
673 else
674 {
676 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
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( SCIPisPositive(scip, val) )
702 {
703 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, -consdata->lhs),
704 !SCIPisInfinity(scip, consdata->rhs)) );
705 }
706 else
707 {
708 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, consdata->rhs),
709 !SCIPisInfinity(scip, -consdata->lhs)) );
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 int k;
902
903 SCIP_VAR** varsbuffer;
904 SCIP_Real* valsbuffer;
905
906 /* copy variables into temporary buffer */
907 SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
908 SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
909 k = 0;
910
911 /* loop over variables and sort out fixed ones */
912 for( v = 0; v < nvars; ++v )
913 {
914 SCIP_VAR* var;
915 SCIP_Real val;
916
917 var = vars[v];
918 val = vals[v];
919
920 assert(var != NULL);
921 if( !SCIPisZero(scip, val) )
922 {
923 /* treat fixed variable as a constant if problem compression is enabled */
925 {
926 constant += SCIPvarGetLbGlobal(var) * val;
927 }
928 else
929 {
930 varsbuffer[k] = var;
931 valsbuffer[k] = val;
932 k++;
933
934 /* update hascontvar and hasnonbinvar flags */
935 if( !(*consdata)->hascontvar )
936 {
938
939 if( vartype != SCIP_VARTYPE_BINARY )
940 {
941 (*consdata)->hasnonbinvar = TRUE;
942
943 if( vartype == SCIP_VARTYPE_CONTINUOUS )
944 (*consdata)->hascontvar = TRUE;
945 }
946 }
947 }
948 }
949 }
950 (*consdata)->nvars = k;
951
952 if( k > 0 )
953 {
954 /* copy the possibly reduced buffer arrays into block */
955 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
956 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) );
957 (*consdata)->varssize = k;
958 }
959 /* free temporary buffer */
960 SCIPfreeBufferArray(scip, &valsbuffer);
961 SCIPfreeBufferArray(scip, &varsbuffer);
962 }
963
964 (*consdata)->eventdata = NULL;
965
966 /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
967 if( !SCIPisZero(scip, constant) )
968 {
969 if( !SCIPisInfinity(scip, REALABS(lhs)) )
970 lhs -= constant;
971
972 if( !SCIPisInfinity(scip, REALABS(rhs)) )
973 rhs -= constant;
974 }
975
976 (*consdata)->row = NULL;
977 (*consdata)->nlrow = NULL;
978 (*consdata)->lhs = lhs;
979 (*consdata)->rhs = rhs;
980 (*consdata)->maxabsval = SCIP_INVALID;
981 (*consdata)->minabsval = SCIP_INVALID;
982 QUAD_ASSIGN((*consdata)->minactivity, SCIP_INVALID);
983 QUAD_ASSIGN((*consdata)->maxactivity, SCIP_INVALID);
984 (*consdata)->lastminactivity = SCIP_INVALID;
985 (*consdata)->lastmaxactivity = SCIP_INVALID;
986 (*consdata)->maxactdelta = SCIP_INVALID;
987 (*consdata)->maxactdeltavar = NULL;
988 (*consdata)->minactivityneginf = -1;
989 (*consdata)->minactivityposinf = -1;
990 (*consdata)->maxactivityneginf = -1;
991 (*consdata)->maxactivityposinf = -1;
992 (*consdata)->minactivityneghuge = -1;
993 (*consdata)->minactivityposhuge = -1;
994 (*consdata)->maxactivityneghuge = -1;
995 (*consdata)->maxactivityposhuge = -1;
996 QUAD_ASSIGN((*consdata)->glbminactivity, SCIP_INVALID);
997 QUAD_ASSIGN((*consdata)->glbmaxactivity, SCIP_INVALID);
998 (*consdata)->lastglbminactivity = SCIP_INVALID;
999 (*consdata)->lastglbmaxactivity = SCIP_INVALID;
1000 (*consdata)->glbminactivityneginf = -1;
1001 (*consdata)->glbminactivityposinf = -1;
1002 (*consdata)->glbmaxactivityneginf = -1;
1003 (*consdata)->glbmaxactivityposinf = -1;
1004 (*consdata)->glbminactivityneghuge = -1;
1005 (*consdata)->glbminactivityposhuge = -1;
1006 (*consdata)->glbmaxactivityneghuge = -1;
1007 (*consdata)->glbmaxactivityposhuge = -1;
1008 (*consdata)->possignature = 0;
1009 (*consdata)->negsignature = 0;
1010 (*consdata)->validmaxabsval = FALSE;
1011 (*consdata)->validminabsval = FALSE;
1012 (*consdata)->validactivities = FALSE;
1013 (*consdata)->validminact = FALSE;
1014 (*consdata)->validmaxact = FALSE;
1015 (*consdata)->validglbminact = FALSE;
1016 (*consdata)->validglbmaxact = FALSE;
1017 (*consdata)->boundstightened = 0;
1018 (*consdata)->presolved = FALSE;
1019 (*consdata)->removedfixings = FALSE;
1020 (*consdata)->validsignature = FALSE;
1021 (*consdata)->changed = TRUE;
1022 (*consdata)->normalized = FALSE;
1023 (*consdata)->upgradetried = FALSE;
1024 (*consdata)->upgraded = FALSE;
1025 (*consdata)->indexsorted = (nvars <= 1);
1026 (*consdata)->merged = (nvars <= 1);
1027 (*consdata)->cliquesadded = FALSE;
1028 (*consdata)->implsadded = FALSE;
1029 (*consdata)->coefsorted = FALSE;
1030 (*consdata)->nbinvars = -1;
1031 (*consdata)->varsdeleted = FALSE;
1032 (*consdata)->rangedrowpropagated = 0;
1033 (*consdata)->checkabsolute = FALSE;
1034
1035 if( SCIPisTransformed(scip) )
1036 {
1037 /* get transformed variables */
1038 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1039 }
1040
1041 /* capture variables */
1042 for( v = 0; v < (*consdata)->nvars; v++ )
1043 {
1044 /* likely implies a deleted variable */
1045 if( (*consdata)->vars[v] == NULL )
1046 {
1047 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1048 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1049 SCIPfreeBlockMemory(scip, consdata);
1050 return SCIP_INVALIDDATA;
1051 }
1052
1053 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1054 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1055 }
1056
1057 return SCIP_OKAY;
1058}
1059
1060/** frees a linear constraint data */
1061static
1063 SCIP* scip, /**< SCIP data structure */
1064 SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1065 )
1066{
1067 int v;
1068
1069 assert(scip != NULL);
1070 assert(consdata != NULL);
1071 assert(*consdata != NULL);
1072 assert((*consdata)->varssize >= 0);
1073
1074 /* release the row */
1075 if( (*consdata)->row != NULL )
1076 {
1077 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1078 }
1079
1080 /* release the nlrow */
1081 if( (*consdata)->nlrow != NULL )
1082 {
1083 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
1084 }
1085
1086 /* release variables */
1087 for( v = 0; v < (*consdata)->nvars; v++ )
1088 {
1089 assert((*consdata)->vars[v] != NULL);
1090 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1091 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1092 }
1093
1094 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1095 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1096 SCIPfreeBlockMemory(scip, consdata);
1097
1098 return SCIP_OKAY;
1099}
1100
1101/** prints linear constraint in CIP format to file stream */
1102static
1104 SCIP* scip, /**< SCIP data structure */
1105 SCIP_CONSDATA* consdata, /**< linear constraint data */
1106 FILE* file /**< output file (or NULL for standard output) */
1107 )
1108{
1109 assert(scip != NULL);
1110 assert(consdata != NULL);
1111
1112 /* print left hand side for ranged rows */
1113 if( !SCIPisInfinity(scip, -consdata->lhs)
1114 && !SCIPisInfinity(scip, consdata->rhs)
1115 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1116 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1117
1118 /* print coefficients and variables */
1119 if( consdata->nvars == 0 )
1120 SCIPinfoMessage(scip, file, "0");
1121 else
1122 {
1123 /* post linear sum of the linear constraint */
1124 SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1125 }
1126
1127 /* print right hand side */
1128 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1129 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1130 else if( !SCIPisInfinity(scip, consdata->rhs) )
1131 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1132 else if( !SCIPisInfinity(scip, -consdata->lhs) )
1133 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1134 else
1135 SCIPinfoMessage(scip, file, " [free]");
1136
1137 return SCIP_OKAY;
1138}
1139
1140/** prints linear constraint and contained solution values of variables to file stream */
1141static
1143 SCIP* scip, /**< SCIP data structure */
1144 SCIP_CONS* cons, /**< linear constraint */
1145 SCIP_SOL* sol, /**< solution to print */
1146 FILE* file /**< output file (or NULL for standard output) */
1147 )
1148{
1149 SCIP_CONSDATA* consdata;
1150
1151 assert(scip != NULL);
1152 assert(cons != NULL);
1153
1154 consdata = SCIPconsGetData(cons);
1155 assert(consdata != NULL);
1156
1158
1159 /* print left hand side for ranged rows */
1160 if( !SCIPisInfinity(scip, -consdata->lhs)
1161 && !SCIPisInfinity(scip, consdata->rhs)
1162 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1163 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1164
1165 /* print coefficients and variables */
1166 if( consdata->nvars == 0 )
1167 SCIPinfoMessage(scip, file, "0");
1168 else
1169 {
1170 int v;
1171
1172 /* post linear sum of the linear constraint */
1173 for( v = 0; v < consdata->nvars; ++v )
1174 {
1175 if( consdata->vals != NULL )
1176 {
1177 if( consdata->vals[v] == 1.0 )
1178 {
1179 if( v > 0 )
1180 SCIPinfoMessage(scip, file, " +");
1181 }
1182 else if( consdata->vals[v] == -1.0 )
1183 SCIPinfoMessage(scip, file, " -");
1184 else
1185 SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1186 }
1187 else if( consdata->nvars > 0 )
1188 SCIPinfoMessage(scip, file, " +");
1189
1190 /* print variable name */
1191 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1192
1193 SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1194 }
1195 }
1196
1197 /* print right hand side */
1198 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1199 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1200 else if( !SCIPisInfinity(scip, consdata->rhs) )
1201 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1202 else if( !SCIPisInfinity(scip, -consdata->lhs) )
1203 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1204 else
1205 SCIPinfoMessage(scip, file, " [free]");
1206
1207 SCIPinfoMessage(scip, file, ";\n");
1208
1209 return SCIP_OKAY;
1210}
1211
1212/** invalidates activity bounds, such that they are recalculated in next get */
1213static
1215 SCIP_CONSDATA* consdata /**< linear constraint */
1216 )
1217{
1218 assert(consdata != NULL);
1219
1220 consdata->validactivities = FALSE;
1221 consdata->validminact = FALSE;
1222 consdata->validmaxact = FALSE;
1223 consdata->validglbminact = FALSE;
1224 consdata->validglbmaxact = FALSE;
1225 consdata->validmaxabsval = FALSE;
1226 consdata->validminabsval = FALSE;
1227 consdata->hasnonbinvalid = FALSE;
1228 QUAD_ASSIGN(consdata->minactivity, SCIP_INVALID);
1229 QUAD_ASSIGN(consdata->maxactivity, SCIP_INVALID);
1230 consdata->lastminactivity = SCIP_INVALID;
1231 consdata->lastmaxactivity = SCIP_INVALID;
1232 consdata->maxabsval = SCIP_INVALID;
1233 consdata->minabsval = SCIP_INVALID;
1234 consdata->maxactdelta = SCIP_INVALID;
1235 consdata->maxactdeltavar = NULL;
1236 consdata->minactivityneginf = -1;
1237 consdata->minactivityposinf = -1;
1238 consdata->maxactivityneginf = -1;
1239 consdata->maxactivityposinf = -1;
1240 consdata->minactivityneghuge = -1;
1241 consdata->minactivityposhuge = -1;
1242 consdata->maxactivityneghuge = -1;
1243 consdata->maxactivityposhuge = -1;
1244 QUAD_ASSIGN(consdata->glbminactivity, SCIP_INVALID);
1245 QUAD_ASSIGN(consdata->glbmaxactivity, SCIP_INVALID);
1246 consdata->lastglbminactivity = SCIP_INVALID;
1247 consdata->lastglbmaxactivity = SCIP_INVALID;
1248 consdata->glbminactivityneginf = -1;
1249 consdata->glbminactivityposinf = -1;
1250 consdata->glbmaxactivityneginf = -1;
1251 consdata->glbmaxactivityposinf = -1;
1252 consdata->glbminactivityneghuge = -1;
1253 consdata->glbminactivityposhuge = -1;
1254 consdata->glbmaxactivityneghuge = -1;
1255 consdata->glbmaxactivityposhuge = -1;
1256}
1257
1258/** compute the pseudo activity of a constraint */
1259static
1261 SCIP* scip, /**< SCIP data structure */
1262 SCIP_CONSDATA* consdata /**< linear constraint data */
1263 )
1264{
1265 int i;
1266 int pseudoactivityposinf;
1267 int pseudoactivityneginf;
1268 SCIP_Real pseudoactivity;
1269 SCIP_Real bound;
1270 SCIP_Real val;
1271
1272 pseudoactivity = 0;
1273 pseudoactivityposinf = 0;
1274 pseudoactivityneginf = 0;
1275
1276 for( i = consdata->nvars - 1; i >= 0; --i )
1277 {
1278 val = consdata->vals[i];
1279 bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1280 if( SCIPisInfinity(scip, bound) )
1281 {
1282 if( val > 0.0 )
1283 pseudoactivityposinf++;
1284 else
1285 pseudoactivityneginf++;
1286 }
1287 else
1288 {
1289 if( SCIPisInfinity(scip, -bound) )
1290 {
1291 if( val > 0.0 )
1292 pseudoactivityneginf++;
1293 else
1294 pseudoactivityposinf++;
1295 }
1296 else
1297 pseudoactivity += val * bound;
1298 }
1299 }
1300
1301 if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1302 return SCIP_INVALID;
1303 else if( pseudoactivityneginf > 0 )
1304 return -SCIPinfinity(scip);
1305 else if( pseudoactivityposinf > 0 )
1306 return SCIPinfinity(scip);
1307
1308 return pseudoactivity;
1309}
1310
1311/** recompute the minactivity of a constraint */
1312static
1314 SCIP* scip, /**< SCIP data structure */
1315 SCIP_CONSDATA* consdata /**< linear constraint data */
1316 )
1317{
1318 int i;
1319 SCIP_Real bound;
1320
1321 QUAD_ASSIGN(consdata->minactivity, 0.0);
1322
1323 for( i = consdata->nvars - 1; i >= 0; --i )
1324 {
1325 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1327 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1328 SCIPquadprecSumQD(consdata->minactivity, consdata->minactivity, consdata->vals[i] * bound);
1329 }
1330
1331 /* the activity was just computed from scratch and is valid now */
1332 consdata->validminact = TRUE;
1333
1334 /* the activity was just computed from scratch, mark it to be reliable */
1335 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
1336}
1337
1338/** recompute the maxactivity of a constraint */
1339static
1341 SCIP* scip, /**< SCIP data structure */
1342 SCIP_CONSDATA* consdata /**< linear constraint data */
1343 )
1344{
1345 int i;
1346 SCIP_Real bound;
1347
1348 QUAD_ASSIGN(consdata->maxactivity, 0.0);
1349
1350 for( i = consdata->nvars - 1; i >= 0; --i )
1351 {
1352 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1354 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1355 SCIPquadprecSumQD(consdata->maxactivity, consdata->maxactivity, consdata->vals[i] * bound);
1356 }
1357
1358 /* the activity was just computed from scratch and is valid now */
1359 consdata->validmaxact = TRUE;
1360
1361 /* the activity was just computed from scratch, mark it to be reliable */
1362 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
1363}
1364
1365/** recompute the global minactivity of a constraint */
1366static
1368 SCIP* scip, /**< SCIP data structure */
1369 SCIP_CONSDATA* consdata /**< linear constraint data */
1370 )
1371{
1372 int i;
1373 SCIP_Real bound;
1374
1375 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
1376
1377 for( i = consdata->nvars - 1; i >= 0; --i )
1378 {
1379 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1381 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1382 SCIPquadprecSumQD(consdata->glbminactivity, consdata->glbminactivity, consdata->vals[i] * bound);
1383 }
1384
1385 /* the activity was just computed from scratch and is valid now */
1386 consdata->validglbminact = TRUE;
1387
1388 /* the activity was just computed from scratch, mark it to be reliable */
1389 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
1390}
1391
1392/** recompute the global maxactivity of a constraint */
1393static
1395 SCIP* scip, /**< SCIP data structure */
1396 SCIP_CONSDATA* consdata /**< linear constraint data */
1397 )
1398{
1399 int i;
1400 SCIP_Real bound;
1401
1402 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
1403
1404 for( i = consdata->nvars - 1; i >= 0; --i )
1405 {
1406 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1408 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1409 SCIPquadprecSumQD(consdata->glbmaxactivity, consdata->glbmaxactivity, consdata->vals[i] * bound);
1410 }
1411
1412 /* the activity was just computed from scratch and is valid now */
1413 consdata->validglbmaxact = TRUE;
1414
1415 /* the activity was just computed from scratch, mark it to be reliable */
1416 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
1417}
1418
1419/** calculates maximum absolute value of coefficients */
1420static
1422 SCIP_CONSDATA* consdata /**< linear constraint data */
1423 )
1424{
1425 SCIP_Real absval;
1426 int i;
1427
1428 assert(consdata != NULL);
1429 assert(!consdata->validmaxabsval);
1430 assert(consdata->maxabsval >= SCIP_INVALID);
1431
1432 consdata->validmaxabsval = TRUE;
1433 consdata->maxabsval = 0.0;
1434 for( i = 0; i < consdata->nvars; ++i )
1435 {
1436 absval = consdata->vals[i];
1437 absval = REALABS(absval);
1438 if( absval > consdata->maxabsval )
1439 consdata->maxabsval = absval;
1440 }
1441}
1442
1443/** calculates minimum absolute value of coefficients */
1444static
1446 SCIP_CONSDATA* consdata /**< linear constraint data */
1447 )
1448{
1449 SCIP_Real absval;
1450 int i;
1451
1452 assert(consdata != NULL);
1453 assert(!consdata->validminabsval);
1454 assert(consdata->minabsval >= SCIP_INVALID);
1455
1456 consdata->validminabsval = TRUE;
1457
1458 if( consdata->nvars > 0 )
1459 consdata->minabsval = REALABS(consdata->vals[0]);
1460 else
1461 consdata->minabsval = 0.0;
1462
1463 for( i = 1; i < consdata->nvars; ++i )
1464 {
1465 absval = consdata->vals[i];
1466 absval = REALABS(absval);
1467 if( absval < consdata->minabsval )
1468 consdata->minabsval = absval;
1469 }
1470}
1471
1472/** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1473static
1475 SCIP_CONSDATA* consdata /**< linear constraint data */
1476 )
1477{
1478 int v;
1479
1480 assert(!consdata->hasnonbinvalid);
1481 consdata->hasnonbinvar = FALSE;
1482 consdata->hascontvar = FALSE;
1483
1484 for( v = consdata->nvars - 1; v >= 0; --v )
1485 {
1486 SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1487
1488 if( vartype != SCIP_VARTYPE_BINARY )
1489 {
1490 consdata->hasnonbinvar = TRUE;
1491
1492 if( vartype == SCIP_VARTYPE_CONTINUOUS )
1493 {
1494 consdata->hascontvar = TRUE;
1495 break;
1496 }
1497 }
1498 }
1499 assert(consdata->hascontvar || v < 0);
1500
1501 consdata->hasnonbinvalid = TRUE;
1502}
1503
1504
1505#ifdef CHECKMAXACTDELTA
1506/** checks that the stored maximal activity delta (if not invalid) is correct */
1507static
1509 SCIP* scip, /**< SCIP data structure */
1510 SCIP_CONSDATA* consdata /**< linear constraint data */
1511 )
1512{
1513 if( consdata->maxactdelta != SCIP_INVALID )
1514 {
1515 SCIP_Real maxactdelta = 0.0;
1516 SCIP_Real domain;
1517 SCIP_Real delta;
1518 SCIP_Real lb;
1519 SCIP_Real ub;
1520 int v;
1521
1522 for( v = consdata->nvars - 1; v >= 0; --v )
1523 {
1524 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1525 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1526
1527 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1528 {
1529 maxactdelta = SCIPinfinity(scip);
1530 break;
1531 }
1532
1533 domain = ub - lb;
1534 delta = REALABS(consdata->vals[v]) * domain;
1535
1536 if( delta > maxactdelta )
1537 {
1538 maxactdelta = delta;
1539 }
1540 }
1541 assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1542 }
1543}
1544#else
1545#define checkMaxActivityDelta(scip, consdata) /**/
1546#endif
1547
1548/** recompute maximal activity contribution for a single variable */
1549static
1551 SCIP* scip, /**< SCIP data structure */
1552 SCIP_CONSDATA* consdata /**< linear constraint data */
1553 )
1554{
1555 SCIP_Real delta;
1556 int v;
1557
1558 consdata->maxactdelta = 0.0;
1559
1560 if( !consdata->hasnonbinvalid )
1561 consdataCheckNonbinvar(consdata);
1562
1563 /* easy case, the problem consists only of binary variables */
1564 if( !consdata->hasnonbinvar )
1565 {
1566 for( v = consdata->nvars - 1; v >= 0; --v )
1567 {
1568 if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1569 {
1570 delta = REALABS(consdata->vals[v]);
1571
1572 if( delta > consdata->maxactdelta )
1573 {
1574 consdata->maxactdelta = delta;
1575 consdata->maxactdeltavar = consdata->vars[v];
1576 }
1577 }
1578 }
1579 return;
1580 }
1581
1582 for( v = consdata->nvars - 1; v >= 0; --v )
1583 {
1584 SCIP_Real domain;
1585 SCIP_Real lb;
1586 SCIP_Real ub;
1587
1588 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1589 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1590
1591 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1592 {
1593 consdata->maxactdelta = SCIPinfinity(scip);
1594 consdata->maxactdeltavar = consdata->vars[v];
1595 break;
1596 }
1597
1598 domain = ub - lb;
1599 delta = REALABS(consdata->vals[v]) * domain;
1600
1601 if( delta > consdata->maxactdelta )
1602 {
1603 consdata->maxactdelta = delta;
1604 consdata->maxactdeltavar = consdata->vars[v];
1605 }
1606 }
1607}
1608
1609
1610/** updates activities for a change in a bound */
1611static
1613 SCIP* scip, /**< SCIP data structure */
1614 SCIP_CONSDATA* consdata, /**< linear constraint data */
1615 SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1616 SCIP_Real oldbound, /**< old bound of variable */
1617 SCIP_Real newbound, /**< new bound of variable */
1618 SCIP_Real val, /**< coefficient of constraint entry */
1619 SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1620 SCIP_Bool global, /**< is it a global or a local bound change? */
1621 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1622 )
1623{
1624 QUAD_MEMBER(SCIP_Real* activity);
1625 QUAD_MEMBER(SCIP_Real delta);
1626 SCIP_Real* lastactivity;
1627 int* activityposinf;
1628 int* activityneginf;
1629 int* activityposhuge;
1630 int* activityneghuge;
1631 SCIP_Real oldcontribution;
1632 SCIP_Real newcontribution;
1633 SCIP_Bool validact;
1634 SCIP_Bool finitenewbound;
1635 SCIP_Bool hugevalnewcont;
1636
1637 assert(scip != NULL);
1638 assert(consdata != NULL);
1639 assert(global || (var != NULL));
1640 assert(consdata->validactivities);
1641 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
1642 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
1643 assert(consdata->lastminactivity < SCIP_INVALID);
1644 assert(consdata->lastmaxactivity < SCIP_INVALID);
1645 assert(consdata->minactivityneginf >= 0);
1646 assert(consdata->minactivityposinf >= 0);
1647 assert(consdata->maxactivityneginf >= 0);
1648 assert(consdata->maxactivityposinf >= 0);
1649 assert(consdata->minactivityneghuge >= 0);
1650 assert(consdata->minactivityposhuge >= 0);
1651 assert(consdata->maxactivityneghuge >= 0);
1652 assert(consdata->maxactivityposhuge >= 0);
1653 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
1654 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
1655 assert(consdata->lastglbminactivity < SCIP_INVALID);
1656 assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1657 assert(consdata->glbminactivityneginf >= 0);
1658 assert(consdata->glbminactivityposinf >= 0);
1659 assert(consdata->glbmaxactivityneginf >= 0);
1660 assert(consdata->glbmaxactivityposinf >= 0);
1661 assert(consdata->glbminactivityneghuge >= 0);
1662 assert(consdata->glbminactivityposhuge >= 0);
1663 assert(consdata->glbmaxactivityneghuge >= 0);
1664 assert(consdata->glbmaxactivityposhuge >= 0);
1665
1666 QUAD_ASSIGN(delta, 0.0);
1667
1668 /* we are updating global activities */
1669 if( global )
1670 {
1671 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1672 * lower bound + pos. coef: update minactivity
1673 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1674 * upper bound + pos. coef: update maxactivity
1675 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1676 */
1677 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1678 {
1679 if( val > 0.0 )
1680 {
1681 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1682 lastactivity = &(consdata->lastglbminactivity);
1683 activityposinf = &(consdata->glbminactivityposinf);
1684 activityneginf = &(consdata->glbminactivityneginf);
1685 activityposhuge = &(consdata->glbminactivityposhuge);
1686 activityneghuge = &(consdata->glbminactivityneghuge);
1687 validact = consdata->validglbminact;
1688 }
1689 else
1690 {
1691 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1692 lastactivity = &(consdata->lastglbmaxactivity);
1693 activityposinf = &(consdata->glbmaxactivityneginf);
1694 activityneginf = &(consdata->glbmaxactivityposinf);
1695 activityposhuge = &(consdata->glbmaxactivityposhuge);
1696 activityneghuge = &(consdata->glbmaxactivityneghuge);
1697 validact = consdata->validglbmaxact;
1698 }
1699 }
1700 else
1701 {
1702 if( val > 0.0 )
1703 {
1704 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1705 lastactivity = &(consdata->lastglbmaxactivity);
1706 activityposinf = &(consdata->glbmaxactivityposinf);
1707 activityneginf = &(consdata->glbmaxactivityneginf);
1708 activityposhuge = &(consdata->glbmaxactivityposhuge);
1709 activityneghuge = &(consdata->glbmaxactivityneghuge);
1710 validact = consdata->validglbmaxact;
1711 }
1712 else
1713 {
1714 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1715 lastactivity = &(consdata->lastglbminactivity);
1716 activityposinf = &(consdata->glbminactivityneginf);
1717 activityneginf = &(consdata->glbminactivityposinf);
1718 activityposhuge = &(consdata->glbminactivityposhuge);
1719 activityneghuge = &(consdata->glbminactivityneghuge);
1720 validact = consdata->validglbminact;
1721 }
1722 }
1723 }
1724 /* we are updating local activities */
1725 else
1726 {
1727 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1728 * lower bound + pos. coef: update minactivity
1729 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1730 * upper bound + pos. coef: update maxactivity
1731 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1732 */
1733 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1734 {
1735 if( val > 0.0 )
1736 {
1737 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1738 lastactivity = &(consdata->lastminactivity);
1739 activityposinf = &(consdata->minactivityposinf);
1740 activityneginf = &(consdata->minactivityneginf);
1741 activityposhuge = &(consdata->minactivityposhuge);
1742 activityneghuge = &(consdata->minactivityneghuge);
1743 validact = consdata->validminact;
1744 }
1745 else
1746 {
1747 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1748 lastactivity = &(consdata->lastmaxactivity);
1749 activityposinf = &(consdata->maxactivityneginf);
1750 activityneginf = &(consdata->maxactivityposinf);
1751 activityposhuge = &(consdata->maxactivityposhuge);
1752 activityneghuge = &(consdata->maxactivityneghuge);
1753 validact = consdata->validmaxact;
1754 }
1755 }
1756 else
1757 {
1758 if( val > 0.0 )
1759 {
1760 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1761 lastactivity = &(consdata->lastmaxactivity);
1762 activityposinf = &(consdata->maxactivityposinf);
1763 activityneginf = &(consdata->maxactivityneginf);
1764 activityposhuge = &(consdata->maxactivityposhuge);
1765 activityneghuge = &(consdata->maxactivityneghuge);
1766 validact = consdata->validmaxact;
1767 }
1768 else
1769 {
1770 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1771 lastactivity = &(consdata->lastminactivity);
1772 activityposinf = &(consdata->minactivityneginf);
1773 activityneginf = &(consdata->minactivityposinf);
1774 activityposhuge = &(consdata->minactivityposhuge);
1775 activityneghuge = &(consdata->minactivityneghuge);
1776 validact = consdata->validminact;
1777 }
1778 }
1779 }
1780
1781 oldcontribution = val * oldbound;
1782 newcontribution = val * newbound;
1783 hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1784 finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1785
1786 if( SCIPisInfinity(scip, REALABS(oldbound)) )
1787 {
1788 /* old bound was +infinity */
1789 if( oldbound > 0.0 )
1790 {
1791 assert((*activityposinf) >= 1);
1792
1793 /* we only have to do something if the new bound is not again +infinity */
1794 if( finitenewbound || newbound < 0.0 )
1795 {
1796 /* decrease the counter for positive infinite contributions */
1797 (*activityposinf)--;
1798
1799 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1800 if( !finitenewbound && newbound < 0.0 )
1801 (*activityneginf)++;
1802 else if( hugevalnewcont )
1803 {
1804 /* if the contribution of this variable is too large, increase the counter for huge values */
1805 if( newcontribution > 0.0 )
1806 (*activityposhuge)++;
1807 else
1808 (*activityneghuge)++;
1809 }
1810 /* "normal case": just add the contribution to the activity */
1811 else
1812 QUAD_ASSIGN(delta, newcontribution);
1813 }
1814 }
1815 /* old bound was -infinity */
1816 else
1817 {
1818 assert(oldbound < 0.0);
1819 assert((*activityneginf) >= 1);
1820
1821 /* we only have to do something ig the new bound is not again -infinity */
1822 if( finitenewbound || newbound > 0.0 )
1823 {
1824 /* decrease the counter for negative infinite contributions */
1825 (*activityneginf)--;
1826
1827 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1828 if( !finitenewbound && newbound > 0.0 )
1829 (*activityposinf)++;
1830 else if( hugevalnewcont )
1831 {
1832 /* if the contribution of this variable is too large, increase the counter for huge values */
1833 if( newcontribution > 0.0 )
1834 (*activityposhuge)++;
1835 else
1836 (*activityneghuge)++;
1837 }
1838 /* "normal case": just add the contribution to the activity */
1839 else
1840 QUAD_ASSIGN(delta, newcontribution);
1841 }
1842 }
1843 }
1844 else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1845 {
1846 /* old contribution was too large and positive */
1847 if( oldcontribution > 0.0 )
1848 {
1849 assert((*activityposhuge) >= 1);
1850
1851 /* decrease the counter for huge positive contributions; it might be increased again later,
1852 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1853 */
1854 (*activityposhuge)--;
1855
1856 if( !finitenewbound )
1857 {
1858 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1859 if( newbound > 0.0 )
1860 (*activityposinf)++;
1861 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1862 else
1863 (*activityneginf)++;
1864 }
1865 else if( hugevalnewcont )
1866 {
1867 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1868 if( newcontribution > 0.0 )
1869 (*activityposhuge)++;
1870 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1871 else
1872 (*activityneghuge)++;
1873 }
1874 /* "normal case": just add the contribution to the activity */
1875 else
1876 QUAD_ASSIGN(delta, newcontribution);
1877 }
1878 /* old contribution was too large and negative */
1879 else
1880 {
1881 assert(oldcontribution < 0.0);
1882 assert((*activityneghuge) >= 1);
1883
1884 /* decrease the counter for huge negative contributions; it might be increased again later,
1885 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1886 */
1887 (*activityneghuge)--;
1888
1889 if( !finitenewbound )
1890 {
1891 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1892 if( newbound > 0.0 )
1893 (*activityposinf)++;
1894 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1895 else
1896 (*activityneginf)++;
1897 }
1898 else if( hugevalnewcont )
1899 {
1900 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1901 if( newcontribution > 0.0 )
1902 (*activityposhuge)++;
1903 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1904 else
1905 (*activityneghuge)++;
1906 }
1907 /* "normal case": just add the contribution to the activity */
1908 else
1909 QUAD_ASSIGN(delta, newcontribution);
1910 }
1911 }
1912 /* old bound was finite and not too large */
1913 else
1914 {
1915 if( !finitenewbound )
1916 {
1917 /* if the new bound is +infinity, the old contribution has to be subtracted
1918 * and the counter for positive infinite contributions has to be increased
1919 */
1920 if( newbound > 0.0 )
1921 {
1922 (*activityposinf)++;
1923 QUAD_ASSIGN(delta, -oldcontribution);
1924 }
1925 /* if the new bound is -infinity, the old contribution has to be subtracted
1926 * and the counter for negative infinite contributions has to be increased
1927 */
1928 else
1929 {
1930 assert(newbound < 0.0 );
1931
1932 (*activityneginf)++;
1933 QUAD_ASSIGN(delta, -oldcontribution);
1934 }
1935 }
1936 /* if the contribution of this variable is too large, increase the counter for huge values */
1937 else if( hugevalnewcont )
1938 {
1939 if( newcontribution > 0.0 )
1940 {
1941 (*activityposhuge)++;
1942 QUAD_ASSIGN(delta, -oldcontribution);
1943 }
1944 else
1945 {
1946 (*activityneghuge)++;
1947 QUAD_ASSIGN(delta, -oldcontribution);
1948 }
1949 }
1950 /* "normal case": just update the activity */
1951 else
1952 {
1953 QUAD_ASSIGN(delta, newcontribution);
1954 SCIPquadprecSumQD(delta, delta, -oldcontribution);
1955 }
1956 }
1957
1958 /* update the activity, if the current value is valid and there was a change in the finite part */
1959 if( validact && (QUAD_TO_DBL(delta) != 0.0) )
1960 {
1961 SCIP_Real curractivity;
1962
1963 /* if the absolute value of the activity is increased, this is regarded as reliable,
1964 * otherwise, we check whether we can still trust the updated value
1965 */
1966 SCIPquadprecSumQD(*activity, *activity, QUAD_TO_DBL(delta));
1967
1968 curractivity = QUAD_TO_DBL(*activity);
1969 assert(!SCIPisInfinity(scip, -curractivity) && !SCIPisInfinity(scip, curractivity));
1970
1971 if( REALABS((*lastactivity)) < REALABS(curractivity) )
1972 {
1973 (*lastactivity) = curractivity;
1974 }
1975 else
1976 {
1977 if( checkreliability && SCIPisUpdateUnreliable(scip, curractivity, (*lastactivity)) )
1978 {
1979 SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1980 (global ? "global " : ""), curractivity);
1981
1982 /* mark the activity that was just changed and is not reliable anymore to be invalid */
1983 if( global )
1984 {
1985 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1986 consdata->validglbminact = FALSE;
1987 else
1988 consdata->validglbmaxact = FALSE;
1989 }
1990 else
1991 {
1992 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1993 consdata->validminact = FALSE;
1994 else
1995 consdata->validmaxact = FALSE;
1996 }
1997 }
1998 }
1999 }
2000}
2001
2002/** updates minimum and maximum activity for a change in lower bound */
2003static
2005 SCIP* scip, /**< SCIP data structure */
2006 SCIP_CONSDATA* consdata, /**< linear constraint data */
2007 SCIP_VAR* var, /**< variable that has been changed */
2008 SCIP_Real oldlb, /**< old lower bound of variable */
2009 SCIP_Real newlb, /**< new lower bound of variable */
2010 SCIP_Real val, /**< coefficient of constraint entry */
2011 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2012 )
2013{
2014 assert(scip != NULL);
2015 assert(consdata != NULL);
2016 assert(var != NULL);
2017
2018 if( consdata->validactivities )
2019 {
2020 consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
2021
2022 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2023 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2024 }
2025}
2026
2027/** updates minimum and maximum activity for a change in upper bound */
2028static
2030 SCIP* scip, /**< SCIP data structure */
2031 SCIP_CONSDATA* consdata, /**< linear constraint data */
2032 SCIP_VAR* var, /**< variable that has been changed */
2033 SCIP_Real oldub, /**< old upper bound of variable */
2034 SCIP_Real newub, /**< new upper bound of variable */
2035 SCIP_Real val, /**< coefficient of constraint entry */
2036 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2037 )
2038{
2039 assert(scip != NULL);
2040 assert(consdata != NULL);
2041 assert(var != NULL);
2042
2043 if( consdata->validactivities )
2044 {
2045 consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
2046
2047 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2048 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2049 }
2050}
2051
2052/** updates minimum and maximum global activity for a change in the global lower bound */
2053static
2055 SCIP* scip, /**< SCIP data structure */
2056 SCIP_CONSDATA* consdata, /**< linear constraint data */
2057 SCIP_Real oldlb, /**< old lower bound of variable */
2058 SCIP_Real newlb, /**< new lower bound of variable */
2059 SCIP_Real val, /**< coefficient of constraint entry */
2060 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2061 )
2062{
2063 assert(scip != NULL);
2064 assert(consdata != NULL);
2065
2066 if( consdata->validactivities )
2067 {
2068 consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2069
2070 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2071 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2072 }
2073}
2074
2075/** updates minimum and maximum global activity for a change in global upper bound */
2076static
2078 SCIP* scip, /**< SCIP data structure */
2079 SCIP_CONSDATA* consdata, /**< linear constraint data */
2080 SCIP_Real oldub, /**< old upper bound of variable */
2081 SCIP_Real newub, /**< new upper bound of variable */
2082 SCIP_Real val, /**< coefficient of constraint entry */
2083 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2084 )
2085{
2086 assert(scip != NULL);
2087 assert(consdata != NULL);
2088
2089 if( consdata->validactivities )
2090 {
2091 consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2092
2093 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2094 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2095 }
2096}
2097
2098/** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2099static
2101 SCIP* scip, /**< SCIP data structure */
2102 SCIP_CONSDATA* consdata, /**< linear constraint data */
2103 SCIP_VAR* var, /**< variable of constraint entry */
2104 SCIP_Real val, /**< coefficient of constraint entry */
2105 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2106 )
2107{
2108 assert(scip != NULL);
2109 assert(consdata != NULL);
2110 assert(var != NULL);
2111
2112 /* update maximum absolute value */
2113 if( consdata->validmaxabsval )
2114 {
2115 SCIP_Real absval;
2116
2117 assert(consdata->maxabsval < SCIP_INVALID);
2118
2119 absval = REALABS(val);
2120 consdata->maxabsval = MAX(consdata->maxabsval, absval);
2121 }
2122
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 minimal and maximal 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
2148/** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2149static
2151 SCIP* scip, /**< SCIP data structure */
2152 SCIP_CONSDATA* consdata, /**< linear constraint data */
2153 SCIP_VAR* var, /**< variable of constraint entry */
2154 SCIP_Real val, /**< coefficient of constraint entry */
2155 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2156 )
2157{
2158 assert(scip != NULL);
2159 assert(consdata != NULL);
2160 assert(var != NULL);
2161
2162 /* invalidate maximum absolute value, if this coefficient was the maximum */
2163 if( consdata->validmaxabsval )
2164 {
2165 SCIP_Real absval;
2166
2167 absval = REALABS(val);
2168
2169 if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2170 {
2171 consdata->validmaxabsval = FALSE;
2172 consdata->maxabsval = SCIP_INVALID;
2173 }
2174 }
2175
2176 /* invalidate minimum absolute value, if this coefficient was the minimum */
2177 if( consdata->validminabsval )
2178 {
2179 SCIP_Real absval;
2180
2181 absval = REALABS(val);
2182
2183 if( SCIPisEQ(scip, absval, consdata->minabsval) )
2184 {
2185 consdata->validminabsval = FALSE;
2186 consdata->minabsval = SCIP_INVALID;
2187 }
2188 }
2189
2190 /* update minimal and maximal activity */
2191 if( consdata->validactivities )
2192 {
2193 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2194 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2195 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2196 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2197
2198 consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2199 consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2200 consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2201 consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2202 }
2203}
2204
2205/** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2206static
2208 SCIP* scip, /**< SCIP data structure */
2209 SCIP_CONSDATA* consdata, /**< linear constraint data */
2210 SCIP_VAR* var, /**< variable of constraint entry */
2211 SCIP_Real oldval, /**< old coefficient of constraint entry */
2212 SCIP_Real newval, /**< new coefficient of constraint entry */
2213 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2214 )
2215{
2216 assert(scip != NULL);
2217 assert(consdata != NULL);
2218 assert(var != NULL);
2219
2220 /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2221 assert(!SCIPisZero(scip, oldval));
2222
2223 /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2224 assert(!SCIPisZero(scip, newval));
2225
2226 /* update maximum absolute value */
2227 if( consdata->validmaxabsval )
2228 {
2229 SCIP_Real absval;
2230
2231 absval = REALABS(newval);
2232
2233 if( SCIPisGE(scip, absval, consdata->maxabsval) )
2234 {
2235 consdata->maxabsval = absval;
2236 }
2237 else
2238 {
2239 absval = REALABS(oldval);
2240
2241 /* invalidate maximum absolute value */
2242 if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2243 {
2244 consdata->validmaxabsval = FALSE;
2245 consdata->maxabsval = SCIP_INVALID;
2246 }
2247 }
2248 }
2249
2250 /* update minimum absolute value */
2251 if( consdata->validminabsval )
2252 {
2253 SCIP_Real absval;
2254
2255 absval = REALABS(newval);
2256
2257 if( SCIPisLE(scip, absval, consdata->minabsval) )
2258 {
2259 consdata->minabsval = absval;
2260 }
2261 else
2262 {
2263 absval = REALABS(oldval);
2264
2265 /* invalidate minimum absolute value */
2266 if( SCIPisEQ(scip, absval, consdata->minabsval) )
2267 {
2268 consdata->validminabsval = FALSE;
2269 consdata->minabsval = SCIP_INVALID;
2270 }
2271 }
2272 }
2273
2274 /* update maximum activity delta */
2275 if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2276 {
2277 SCIP_Real domain;
2278 SCIP_Real delta;
2279
2282
2284 delta = REALABS(newval) * domain;
2285
2286 if( delta > consdata->maxactdelta )
2287 {
2288 consdata->maxactdelta = delta;
2289 consdata->maxactdeltavar = var;
2290 }
2291 else
2292 {
2293 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2294 if( consdata->maxactdeltavar == var )
2295 consdata->maxactdelta = SCIP_INVALID;
2296 }
2297 }
2298
2299 /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2300 consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2301 consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2302}
2303
2304/** returns the maximum absolute value of all coefficients in the constraint */
2305static
2307 SCIP_CONSDATA* consdata /**< linear constraint data */
2308 )
2309{
2310 assert(consdata != NULL);
2311
2312 if( !consdata->validmaxabsval )
2313 consdataCalcMaxAbsval(consdata);
2314 assert(consdata->validmaxabsval);
2315 assert(consdata->maxabsval < SCIP_INVALID);
2316
2317 return consdata->maxabsval;
2318}
2319
2320/** returns the minimum absolute value of all coefficients in the constraint */
2321static
2323 SCIP_CONSDATA* consdata /**< linear constraint data */
2324 )
2325{
2326 assert(consdata != NULL);
2327
2328 if( !consdata->validminabsval )
2329 consdataCalcMinAbsval(consdata);
2330 assert(consdata->validminabsval);
2331 assert(consdata->minabsval < SCIP_INVALID);
2332
2333 return consdata->minabsval;
2334}
2335
2336/** calculates minimum and maximum local and global activity for constraint from scratch;
2337 * additionally recalculates maximum absolute value of coefficients
2338 */
2339static
2341 SCIP* scip, /**< SCIP data structure */
2342 SCIP_CONSDATA* consdata /**< linear constraint data */
2343 )
2344{
2345 int i;
2346
2347 assert(scip != NULL);
2348 assert(consdata != NULL);
2349 assert(!consdata->validactivities);
2350 assert(QUAD_TO_DBL(consdata->minactivity) >= SCIP_INVALID || consdata->validminact);
2351 assert(QUAD_TO_DBL(consdata->maxactivity) >= SCIP_INVALID || consdata->validmaxact);
2352 assert(QUAD_TO_DBL(consdata->glbminactivity) >= SCIP_INVALID || consdata->validglbminact);
2353 assert(QUAD_TO_DBL(consdata->glbmaxactivity) >= SCIP_INVALID || consdata->validglbmaxact);
2354
2355 consdata->validmaxabsval = TRUE;
2356 consdata->validminabsval = TRUE;
2357 consdata->validactivities = TRUE;
2358 consdata->validminact = TRUE;
2359 consdata->validmaxact = TRUE;
2360 consdata->validglbminact = TRUE;
2361 consdata->validglbmaxact = TRUE;
2362 consdata->maxabsval = 0.0;
2363 consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2364 QUAD_ASSIGN(consdata->minactivity, 0.0);
2365 QUAD_ASSIGN(consdata->maxactivity, 0.0);
2366 consdata->lastminactivity = 0.0;
2367 consdata->lastmaxactivity = 0.0;
2368 consdata->minactivityneginf = 0;
2369 consdata->minactivityposinf = 0;
2370 consdata->maxactivityneginf = 0;
2371 consdata->maxactivityposinf = 0;
2372 consdata->minactivityneghuge = 0;
2373 consdata->minactivityposhuge = 0;
2374 consdata->maxactivityneghuge = 0;
2375 consdata->maxactivityposhuge = 0;
2376 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
2377 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
2378 consdata->lastglbminactivity = 0.0;
2379 consdata->lastglbmaxactivity = 0.0;
2380 consdata->glbminactivityneginf = 0;
2381 consdata->glbminactivityposinf = 0;
2382 consdata->glbmaxactivityneginf = 0;
2383 consdata->glbmaxactivityposinf = 0;
2384 consdata->glbminactivityneghuge = 0;
2385 consdata->glbminactivityposhuge = 0;
2386 consdata->glbmaxactivityneghuge = 0;
2387 consdata->glbmaxactivityposhuge = 0;
2388
2389 for( i = 0; i < consdata->nvars; ++i )
2390 consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2391
2392 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
2393 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
2394 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
2395 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2396}
2397
2398/** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2399 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2400 */
2401static
2403 SCIP* scip, /**< SCIP data structure */
2404 SCIP_CONSDATA* consdata, /**< linear constraint */
2405 int posinf, /**< number of coefficients contributing pos. infinite value */
2406 int neginf, /**< number of coefficients contributing neg. infinite value */
2407 int poshuge, /**< number of coefficients contributing huge pos. value */
2408 int neghuge, /**< number of coefficients contributing huge neg. value */
2409 SCIP_Real delta, /**< value to subtract from stored minactivity
2410 * (contribution of the variable set to zero when getting residual activity) */
2411 SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2412 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2413 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2414 SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
2415 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2416 SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2417 )
2418{
2419 assert(scip != NULL);
2420 assert(consdata != NULL);
2421 assert(posinf >= 0);
2422 assert(neginf >= 0);
2423 assert(poshuge >= 0);
2424 assert(neghuge >= 0);
2425 assert(minactivity != NULL);
2426 assert(istight != NULL);
2427 assert(issettoinfinity != NULL);
2428
2429 /* if we have neg. infinite contributions, the minactivity is -infty */
2430 if( neginf > 0 )
2431 {
2432 *minactivity = -SCIPinfinity(scip);
2433 *issettoinfinity = TRUE;
2434 *istight = posinf == 0;
2435 }
2436 /* if we have pos. (and no neg.) infinite contributions, the minactivity is +infty */
2437 else if( posinf > 0 )
2438 {
2439 *minactivity = SCIPinfinity(scip);
2440 *issettoinfinity = TRUE;
2441 *istight = TRUE;
2442 }
2443 /* if we have neg. huge contributions or do not need a good relaxation, we just return -infty as minactivity */
2444 else if( neghuge > 0 || ( poshuge > 0 && !goodrelax ) )
2445 {
2446 *minactivity = -SCIPinfinity(scip);
2447 *issettoinfinity = TRUE;
2448 *istight = FALSE;
2449 }
2450 else
2451 {
2452 SCIP_Real QUAD(tmpactivity);
2453
2454 /* recompute minactivity if it is not valid */
2455 if( global )
2456 {
2457 if( !consdata->validglbminact )
2459 assert(consdata->validglbminact);
2460
2461 QUAD_ASSIGN_Q(tmpactivity, consdata->glbminactivity);
2462 }
2463 else
2464 {
2465 if( !consdata->validminact )
2467 assert(consdata->validminact);
2468
2469 QUAD_ASSIGN_Q(tmpactivity, consdata->minactivity);
2470 }
2471
2472 /* calculate residual minactivity */
2473 SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
2474
2475 /* we have no infinite and no neg. huge contributions, but pos. huge contributions; a feasible relaxation of the
2476 * minactivity is given by adding the number of positive huge contributions times the huge value
2477 */
2478 if( poshuge > 0 )
2479 {
2480 SCIPquadprecSumQD(tmpactivity, tmpactivity, poshuge * SCIPgetHugeValue(scip));
2481 *istight = FALSE;
2482 }
2483 /* all counters are zero, so the minactivity is tight */
2484 else
2485 *istight = TRUE;
2486
2487 /* round residual minactivity */
2488 *minactivity = QUAD_TO_DBL(tmpactivity);
2489 *issettoinfinity = FALSE;
2490 }
2491}
2492
2493/** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2494 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2495 */
2496static
2498 SCIP* scip, /**< SCIP data structure */
2499 SCIP_CONSDATA* consdata, /**< linear constraint */
2500 int posinf, /**< number of coefficients contributing pos. infinite value */
2501 int neginf, /**< number of coefficients contributing neg. infinite value */
2502 int poshuge, /**< number of coefficients contributing huge pos. value */
2503 int neghuge, /**< number of coefficients contributing huge neg. value */
2504 SCIP_Real delta, /**< value to subtract from stored maxactivity
2505 * (contribution of the variable set to zero when getting residual activity) */
2506 SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2507 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2508 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2509 SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
2510 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2511 SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2512 )
2513{
2514 assert(scip != NULL);
2515 assert(consdata != NULL);
2516 assert(posinf >= 0);
2517 assert(neginf >= 0);
2518 assert(poshuge >= 0);
2519 assert(neghuge >= 0);
2520 assert(maxactivity != NULL);
2521 assert(istight != NULL);
2522 assert(issettoinfinity != NULL);
2523
2524 /* if we have pos. infinite contributions, the maxactivity is +infty */
2525 if( posinf > 0 )
2526 {
2527 *maxactivity = SCIPinfinity(scip);
2528 *issettoinfinity = TRUE;
2529 *istight = neginf == 0;
2530 }
2531 /* if we have neg. (and no pos.) infinite contributions, the maxactivity is -infty */
2532 else if( neginf > 0 )
2533 {
2534 *maxactivity = -SCIPinfinity(scip);
2535 *issettoinfinity = TRUE;
2536 *istight = TRUE;
2537 }
2538 /* if we have pos. huge contributions or do not need a good relaxation, we just return +infty as maxactivity */
2539 else if( poshuge > 0 || ( neghuge > 0 && !goodrelax ) )
2540 {
2541 *maxactivity = SCIPinfinity(scip);
2542 *issettoinfinity = TRUE;
2543 *istight = FALSE;
2544 }
2545 else
2546 {
2547 SCIP_Real QUAD(tmpactivity);
2548
2549 /* recompute maxactivity if it is not valid */
2550 if( global )
2551 {
2552 if( !consdata->validglbmaxact )
2554 assert(consdata->validglbmaxact);
2555
2556 QUAD_ASSIGN_Q(tmpactivity, consdata->glbmaxactivity);
2557 }
2558 else
2559 {
2560 if( !consdata->validmaxact )
2562 assert(consdata->validmaxact);
2563
2564 QUAD_ASSIGN_Q(tmpactivity, consdata->maxactivity);
2565 }
2566
2567 /* calculate residual maxactivity */
2568 SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
2569
2570 /* we have no infinite and no pos. huge contributions, but neg. huge contributions; a feasible relaxation of the
2571 * maxactivity is given by subtracting the number of negative huge contributions times the huge value
2572 */
2573 if( neghuge > 0 )
2574 {
2575 SCIPquadprecSumQD(tmpactivity, tmpactivity, -neghuge * SCIPgetHugeValue(scip));
2576 *istight = FALSE;
2577 }
2578 /* all counters are zero, so the maxactivity is tight */
2579 else
2580 *istight = TRUE;
2581
2582 /* round residual maxactivity */
2583 *maxactivity = QUAD_TO_DBL(tmpactivity);
2584 *issettoinfinity = FALSE;
2585 }
2586}
2587
2588/** gets activity bounds for constraint */
2589static
2591 SCIP* scip, /**< SCIP data structure */
2592 SCIP_CONSDATA* consdata, /**< linear constraint */
2593 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2594 * relaxed activities ignored, anyway? */
2595 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2596 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2597 SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
2598 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2599 SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
2600 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2601 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2602 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2603
2604 )
2605{
2606 assert(scip != NULL);
2607 assert(consdata != NULL);
2608 assert(minactivity != NULL);
2609 assert(maxactivity != NULL);
2610 assert(isminsettoinfinity != NULL);
2611 assert(ismaxsettoinfinity != NULL);
2612
2613 if( !consdata->validactivities )
2614 {
2615 consdataCalcActivities(scip, consdata);
2616 assert(consdata->validminact);
2617 assert(consdata->validmaxact);
2618 }
2619 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2620 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2621 assert(consdata->minactivityneginf >= 0);
2622 assert(consdata->minactivityposinf >= 0);
2623 assert(consdata->maxactivityneginf >= 0);
2624 assert(consdata->maxactivityposinf >= 0);
2625
2626 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2627 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2628 minactivity, ismintight, isminsettoinfinity);
2629
2630 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2631 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2632 maxactivity, ismaxtight, ismaxsettoinfinity);
2633}
2634
2635/** calculates activity bounds for constraint after setting variable to zero */
2636static
2638 SCIP* scip, /**< SCIP data structure */
2639 SCIP_CONSDATA* consdata, /**< linear constraint */
2640 SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2641 SCIP_Real* resactivity, /**< pointer to store the residual activity */
2642 SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2643 SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2644 )
2645{
2646 SCIP_VAR* var;
2647 SCIP_Real val;
2648 SCIP_Real lb;
2649 SCIP_Real ub;
2650 int v;
2651
2652 assert(scip != NULL);
2653 assert(consdata != NULL);
2654 assert(cancelvar != NULL);
2655 assert(resactivity != NULL);
2656
2657 *resactivity = 0.0;
2658
2659 for( v = 0; v < consdata->nvars; ++v )
2660 {
2661 var = consdata->vars[v];
2662 assert(var != NULL);
2663 if( var == cancelvar )
2664 continue;
2665
2666 val = consdata->vals[v];
2667
2668 if( useglobalbounds )
2669 {
2670 lb = SCIPvarGetLbGlobal(var);
2671 ub = SCIPvarGetUbGlobal(var);
2672 }
2673 else
2674 {
2675 lb = SCIPvarGetLbLocal(var);
2676 ub = SCIPvarGetUbLocal(var);
2677 }
2678
2679 assert(!SCIPisZero(scip, val));
2680 assert(SCIPisLE(scip, lb, ub));
2681
2682 if( val > 0.0 )
2683 {
2684 if( isminresact )
2685 {
2686 assert(!SCIPisInfinity(scip, -lb));
2687 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2688 *resactivity += val*lb;
2689 }
2690 else
2691 {
2692 assert(!SCIPisInfinity(scip, ub));
2693 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2694 *resactivity += val*ub;
2695 }
2696 }
2697 else
2698 {
2699 if( isminresact)
2700 {
2701 assert(!SCIPisInfinity(scip, ub));
2702 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2703 *resactivity += val*ub;
2704 }
2705 else
2706 {
2707 assert(!SCIPisInfinity(scip, -lb));
2708 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2709 *resactivity += val*lb;
2710 }
2711 }
2712 }
2713 assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2714}
2715
2716/** gets activity bounds for constraint after setting variable to zero */
2717static
2719 SCIP* scip, /**< SCIP data structure */
2720 SCIP_CONSDATA* consdata, /**< linear constraint */
2721 SCIP_VAR* var, /**< variable to calculate activity residual for */
2722 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2723 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2724 * relaxed acticities ignored, anyway? */
2725 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2726 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2727 SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
2728 * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
2729 SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
2730 * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
2731 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2732 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2733 )
2734{
2735 SCIP_Real minactbound;
2736 SCIP_Real maxactbound;
2737 SCIP_Real absval;
2738
2739 assert(scip != NULL);
2740 assert(consdata != NULL);
2741 assert(var != NULL);
2742 assert(minresactivity != NULL);
2743 assert(maxresactivity != NULL);
2744 assert(ismintight != NULL);
2745 assert(ismaxtight != NULL);
2746 assert(isminsettoinfinity != NULL);
2747 assert(ismaxsettoinfinity != NULL);
2748
2749 /* get activity bounds of linear constraint */
2750 if( !consdata->validactivities )
2751 {
2752 consdataCalcActivities(scip, consdata);
2753 assert(consdata->validminact);
2754 assert(consdata->validmaxact);
2755 }
2756 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2757 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2758 assert(consdata->minactivityneginf >= 0);
2759 assert(consdata->minactivityposinf >= 0);
2760 assert(consdata->maxactivityneginf >= 0);
2761 assert(consdata->maxactivityposinf >= 0);
2762 assert(consdata->minactivityneghuge >= 0);
2763 assert(consdata->minactivityposhuge >= 0);
2764 assert(consdata->maxactivityneghuge >= 0);
2765 assert(consdata->maxactivityposhuge >= 0);
2766
2767 if( val > 0.0 )
2768 {
2769 minactbound = SCIPvarGetLbLocal(var);
2770 maxactbound = SCIPvarGetUbLocal(var);
2771 absval = val;
2772 }
2773 else
2774 {
2775 minactbound = -SCIPvarGetUbLocal(var);
2776 maxactbound = -SCIPvarGetLbLocal(var);
2777 absval = -val;
2778 }
2779
2780 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2781 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2782 */
2783 if( SCIPisInfinity(scip, minactbound) )
2784 {
2785 assert(consdata->minactivityposinf >= 1);
2786
2787 getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2788 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2789 minresactivity, ismintight, isminsettoinfinity);
2790 }
2791 else if( SCIPisInfinity(scip, -minactbound) )
2792 {
2793 assert(consdata->minactivityneginf >= 1);
2794
2795 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2796 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2797 minresactivity, ismintight, isminsettoinfinity);
2798 }
2799 else if( SCIPisHugeValue(scip, minactbound * absval) )
2800 {
2801 assert(consdata->minactivityposhuge >= 1);
2802
2803 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2804 consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2805 minresactivity, ismintight, isminsettoinfinity);
2806 }
2807 else if( SCIPisHugeValue(scip, -minactbound * absval) )
2808 {
2809 assert(consdata->minactivityneghuge >= 1);
2810
2811 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2812 consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2813 minresactivity, ismintight, isminsettoinfinity);
2814 }
2815 else
2816 {
2817 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2818 consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2819 minresactivity, ismintight, isminsettoinfinity);
2820 }
2821
2822 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2823 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2824 */
2825 if( SCIPisInfinity(scip, -maxactbound) )
2826 {
2827 assert(consdata->maxactivityneginf >= 1);
2828
2829 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2830 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2831 maxresactivity, ismaxtight, ismaxsettoinfinity);
2832 }
2833 else if( SCIPisInfinity(scip, maxactbound) )
2834 {
2835 assert(consdata->maxactivityposinf >= 1);
2836
2837 getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2838 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2839 maxresactivity, ismaxtight, ismaxsettoinfinity);
2840 }
2841 else if( SCIPisHugeValue(scip, absval * maxactbound) )
2842 {
2843 assert(consdata->maxactivityposhuge >= 1);
2844
2845 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2846 consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2847 maxresactivity, ismaxtight, ismaxsettoinfinity);
2848 }
2849 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2850 {
2851 assert(consdata->maxactivityneghuge >= 1);
2852
2853 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2854 consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2855 maxresactivity, ismaxtight, ismaxsettoinfinity);
2856 }
2857 else
2858 {
2859 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2860 consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2861 maxresactivity, ismaxtight, ismaxsettoinfinity);
2862 }
2863}
2864
2865/** gets global activity bounds for constraint */
2866static
2868 SCIP* scip, /**< SCIP data structure */
2869 SCIP_CONSDATA* consdata, /**< linear constraint */
2870 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2871 * relaxed acticities ignored, anyway? */
2872 SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2873 SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2874 SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
2875 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2876 SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
2877 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2878 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2879 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2880 )
2881{
2882 assert(scip != NULL);
2883 assert(consdata != NULL);
2884 assert((glbminactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL)
2885 || (glbmaxactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
2886
2887 if( !consdata->validactivities )
2888 {
2889 consdataCalcActivities(scip, consdata);
2890 assert(consdata->validglbminact);
2891 assert(consdata->validglbmaxact);
2892 }
2893 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2894 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2895 assert(consdata->glbminactivityneginf >= 0);
2896 assert(consdata->glbminactivityposinf >= 0);
2897 assert(consdata->glbmaxactivityneginf >= 0);
2898 assert(consdata->glbmaxactivityposinf >= 0);
2899 assert(consdata->glbminactivityneghuge >= 0);
2900 assert(consdata->glbminactivityposhuge >= 0);
2901 assert(consdata->glbmaxactivityneghuge >= 0);
2902 assert(consdata->glbmaxactivityposhuge >= 0);
2903
2904 if( glbminactivity != NULL )
2905 {
2906 assert(isminsettoinfinity != NULL);
2907 assert(ismintight != NULL);
2908
2909 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2910 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2911 glbminactivity, ismintight, isminsettoinfinity);
2912 }
2913
2914 if( glbmaxactivity != NULL )
2915 {
2916 assert(ismaxsettoinfinity != NULL);
2917 assert(ismaxtight != NULL);
2918
2919 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2920 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2921 glbmaxactivity, ismaxtight, ismaxsettoinfinity);
2922 }
2923}
2924
2925/** gets global activity bounds for constraint after setting variable to zero */
2926static
2928 SCIP* scip, /**< SCIP data structure */
2929 SCIP_CONSDATA* consdata, /**< linear constraint */
2930 SCIP_VAR* var, /**< variable to calculate activity residual for */
2931 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2932 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2933 * relaxed acticities ignored, anyway? */
2934 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2935 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2936 SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
2937 * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
2938 SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
2939 * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
2940 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2941 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2942 )
2943{
2944 SCIP_Real minactbound;
2945 SCIP_Real maxactbound;
2946 SCIP_Real absval;
2947
2948 assert(scip != NULL);
2949 assert(consdata != NULL);
2950 assert(var != NULL);
2951 assert((minresactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL )
2952 || (maxresactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
2953
2954 /* get activity bounds of linear constraint */
2955 if( !consdata->validactivities )
2956 consdataCalcActivities(scip, consdata);
2957
2958 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2959 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2960 assert(consdata->glbminactivityneginf >= 0);
2961 assert(consdata->glbminactivityposinf >= 0);
2962 assert(consdata->glbmaxactivityneginf >= 0);
2963 assert(consdata->glbmaxactivityposinf >= 0);
2964
2965 if( val > 0.0 )
2966 {
2967 minactbound = SCIPvarGetLbGlobal(var);
2968 maxactbound = SCIPvarGetUbGlobal(var);
2969 absval = val;
2970 }
2971 else
2972 {
2973 minactbound = -SCIPvarGetUbGlobal(var);
2974 maxactbound = -SCIPvarGetLbGlobal(var);
2975 absval = -val;
2976 }
2977
2978 if( minresactivity != NULL )
2979 {
2980 assert(isminsettoinfinity != NULL);
2981 assert(ismintight != NULL);
2982
2983 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2984 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2985 */
2986 if( SCIPisInfinity(scip, minactbound) )
2987 {
2988 assert(consdata->glbminactivityposinf >= 1);
2989
2990 getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2991 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2992 minresactivity, ismintight, isminsettoinfinity);
2993 }
2994 else if( SCIPisInfinity(scip, -minactbound) )
2995 {
2996 assert(consdata->glbminactivityneginf >= 1);
2997
2998 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2999 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3000 minresactivity, ismintight, isminsettoinfinity);
3001 }
3002 else if( SCIPisHugeValue(scip, minactbound * absval) )
3003 {
3004 assert(consdata->glbminactivityposhuge >= 1);
3005
3006 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3007 consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3008 minresactivity, ismintight, isminsettoinfinity);
3009 }
3010 else if( SCIPisHugeValue(scip, -minactbound * absval) )
3011 {
3012 assert(consdata->glbminactivityneghuge >= 1);
3013
3014 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3015 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
3016 minresactivity, ismintight, isminsettoinfinity);
3017 }
3018 else
3019 {
3020 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3021 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
3022 goodrelax, minresactivity, ismintight, isminsettoinfinity);
3023 }
3024 }
3025
3026 if( maxresactivity != NULL )
3027 {
3028 assert(ismaxsettoinfinity != NULL);
3029 assert(ismaxtight != NULL);
3030
3031 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
3032 * and contribution of variable set to zero that has to be subtracted from finite part of activity
3033 */
3034 if( SCIPisInfinity(scip, -maxactbound) )
3035 {
3036 assert(consdata->glbmaxactivityneginf >= 1);
3037
3038 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
3039 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3040 maxresactivity, ismaxtight, ismaxsettoinfinity);
3041 }
3042 else if( SCIPisInfinity(scip, maxactbound) )
3043 {
3044 assert(consdata->glbmaxactivityposinf >= 1);
3045
3046 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
3047 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3048 maxresactivity, ismaxtight, ismaxsettoinfinity);
3049 }
3050 else if( SCIPisHugeValue(scip, absval * maxactbound) )
3051 {
3052 assert(consdata->glbmaxactivityposhuge >= 1);
3053
3054 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3055 consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3056 maxresactivity, ismaxtight, ismaxsettoinfinity);
3057 }
3058 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3059 {
3060 assert(consdata->glbmaxactivityneghuge >= 1);
3061
3062 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3063 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3064 maxresactivity, ismaxtight, ismaxsettoinfinity);
3065 }
3066 else
3067 {
3068 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3069 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3070 goodrelax, maxresactivity, ismaxtight, ismaxsettoinfinity);
3071 }
3072 }
3073}
3074
3075/** calculates the activity of the linear constraint for given solution */
3076static
3078 SCIP* scip, /**< SCIP data structure */
3079 SCIP_CONSDATA* consdata, /**< linear constraint data */
3080 SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3081 )
3082{
3083 SCIP_Real activity;
3084
3085 assert(scip != NULL);
3086 assert(consdata != NULL);
3087
3088 if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3089 activity = consdataComputePseudoActivity(scip, consdata);
3090 else
3091 {
3092 SCIP_Real solval;
3093 int nposinf;
3094 int nneginf;
3095 SCIP_Bool negsign;
3096 int v;
3097
3098 activity = 0.0;
3099 nposinf = 0;
3100 nneginf = 0;
3101
3102 for( v = 0; v < consdata->nvars; ++v )
3103 {
3104 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3105
3106 if( consdata->vals[v] < 0 )
3107 negsign = TRUE;
3108 else
3109 negsign = FALSE;
3110
3111 if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3112 ++nposinf;
3113 else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3114 ++nneginf;
3115 else
3116 activity += consdata->vals[v] * solval;
3117 }
3118 assert(nneginf >= 0 && nposinf >= 0);
3119
3120 SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3121
3122 /* check for amount of infinity values and correct the activity */
3123 if( nposinf > 0 && nneginf > 0 )
3124 activity = (consdata->rhs + consdata->lhs) / 2;
3125 else if( nposinf > 0 )
3126 activity = SCIPinfinity(scip);
3127 else if( nneginf > 0 )
3128 activity = -SCIPinfinity(scip);
3129
3130 SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3131 }
3132
3133 if( activity == SCIP_INVALID ) /*lint !e777*/
3134 return activity;
3135 else if( activity < 0 )
3136 activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3137 else
3138 activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3139
3140 return activity;
3141}
3142
3143/** calculates the feasibility of the linear constraint for given solution */
3144static
3146 SCIP* scip, /**< SCIP data structure */
3147 SCIP_CONSDATA* consdata, /**< linear constraint data */
3148 SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3149 )
3150{
3151 SCIP_Real activity;
3152
3153 assert(scip != NULL);
3154 assert(consdata != NULL);
3155
3156 activity = consdataGetActivity(scip, consdata, sol);
3157
3158 if( activity == SCIP_INVALID ) /*lint !e777*/
3159 return -SCIPinfinity(scip);
3160
3161 return MIN(consdata->rhs - activity, activity - consdata->lhs);
3162}
3163
3164/** updates bit signatures after adding a single coefficient */
3165static
3167 SCIP_CONSDATA* consdata, /**< linear constraint data */
3168 int pos /**< position of coefficient to update signatures for */
3169 )
3170{
3171 uint64_t varsignature;
3172 SCIP_Real lb;
3173 SCIP_Real ub;
3174 SCIP_Real val;
3175
3176 assert(consdata != NULL);
3177 assert(consdata->validsignature);
3178
3179 varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3180 lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3181 ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3182 val = consdata->vals[pos];
3183 if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3184 consdata->possignature |= varsignature;
3185 if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3186 consdata->negsignature |= varsignature;
3187}
3188
3189/** calculates the bit signatures of the given constraint data */
3190static
3192 SCIP_CONSDATA* consdata /**< linear constraint data */
3193 )
3194{
3195 assert(consdata != NULL);
3196
3197 if( !consdata->validsignature )
3198 {
3199 int i;
3200
3201 consdata->validsignature = TRUE;
3202 consdata->possignature = 0;
3203 consdata->negsignature = 0;
3204 for( i = 0; i < consdata->nvars; ++i )
3205 consdataUpdateSignatures(consdata, i);
3206 }
3207}
3208
3209/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3210static
3212{ /*lint --e{715}*/
3213 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3214 SCIP_VAR* var1;
3215 SCIP_VAR* var2;
3216
3217 assert(consdata != NULL);
3218 assert(0 <= ind1 && ind1 < consdata->nvars);
3219 assert(0 <= ind2 && ind2 < consdata->nvars);
3220
3221 var1 = consdata->vars[ind1];
3222 var2 = consdata->vars[ind2];
3223
3224 /* exactly one variable is binary */
3225 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3226 {
3227 return (SCIPvarIsBinary(var1) ? -1 : +1);
3228 }
3229 /* both variables are binary */
3230 else if( SCIPvarIsBinary(var1) )
3231 {
3232 return SCIPvarCompare(var1, var2);
3233 }
3234 else
3235 {
3236 SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3237 SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3238
3239 if( vartype1 < vartype2 )
3240 return -1;
3241 else if( vartype1 > vartype2 )
3242 return +1;
3243 else
3244 return SCIPvarCompare(var1, var2);
3245 }
3246}
3247
3248/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3249static
3250SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
3251{ /*lint --e{715}*/
3252 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3253 SCIP_VAR* var1;
3254 SCIP_VAR* var2;
3255
3256 assert(consdata != NULL);
3257 assert(0 <= ind1 && ind1 < consdata->nvars);
3258 assert(0 <= ind2 && ind2 < consdata->nvars);
3259
3260 var1 = consdata->vars[ind1];
3261 var2 = consdata->vars[ind2];
3262
3263 /* exactly one variable is binary */
3264 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3265 {
3266 return (SCIPvarIsBinary(var1) ? -1 : +1);
3267 }
3268 /* both variables are binary */
3269 else if( SCIPvarIsBinary(var1) )
3270 {
3271 SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3272 SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3273
3274 if( EPSGT(abscoef1, abscoef2, 1e-9) )
3275 return -1;
3276 else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3277 return +1;
3278 else
3279 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3280 }
3281 else
3282 {
3283 SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3284 SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3285
3286 if( vartype1 < vartype2 )
3287 {
3288 return -1;
3289 }
3290 else if( vartype1 > vartype2 )
3291 {
3292 return +1;
3293 }
3294 else
3295 {
3296 /* both variables are continuous */
3297 if( !SCIPvarIsIntegral(var1) )
3298 {
3299 assert(!SCIPvarIsIntegral(var2));
3300 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3301 }
3302 else
3303 {
3304 SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3305 SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3306
3307 if( EPSGT(abscont1, abscont2, 1e-9) )
3308 return -1;
3309 else if( EPSGT(abscont2, abscont1, 1e-9) )
3310 return +1;
3311 else
3312 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3313 }
3314 }
3315 }
3316}
3317
3318/** permutes the constraint's variables according to a given permutation. */
3319static
3321 SCIP_CONSDATA* consdata, /**< the constraint data */
3322 int* perm, /**< the target permutation */
3323 int nvars /**< the number of variables */
3324 )
3325{ /*lint --e{715}*/
3326 SCIP_VAR* varv;
3327 SCIP_EVENTDATA* eventdatav;
3328 SCIP_Real valv;
3329 int v;
3330 int i;
3331 int nexti;
3332
3333 assert(perm != NULL);
3334 assert(consdata != NULL);
3335
3336 /* permute the variables in the linear constraint according to the target permutation */
3337 eventdatav = NULL;
3338 for( v = 0; v < nvars; ++v )
3339 {
3340 if( perm[v] != v )
3341 {
3342 varv = consdata->vars[v];
3343 valv = consdata->vals[v];
3344 if( consdata->eventdata != NULL )
3345 eventdatav = consdata->eventdata[v];
3346 i = v;
3347 do
3348 {
3349 assert(0 <= perm[i] && perm[i] < nvars);
3350 assert(perm[i] != i);
3351 consdata->vars[i] = consdata->vars[perm[i]];
3352 consdata->vals[i] = consdata->vals[perm[i]];
3353 if( consdata->eventdata != NULL )
3354 {
3355 consdata->eventdata[i] = consdata->eventdata[perm[i]];
3356 consdata->eventdata[i]->varpos = i;
3357 }
3358 nexti = perm[i];
3359 perm[i] = i;
3360 i = nexti;
3361 }
3362 while( perm[i] != v );
3363 consdata->vars[i] = varv;
3364 consdata->vals[i] = valv;
3365 if( consdata->eventdata != NULL )
3366 {
3367 consdata->eventdata[i] = eventdatav;
3368 consdata->eventdata[i]->varpos = i;
3369 }
3370 perm[i] = i;
3371 }
3372 }
3373#ifdef SCIP_DEBUG
3374 /* check sorting */
3375 for( v = 0; v < nvars; ++v )
3376 {
3377 assert(perm[v] == v);
3378 assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3379 }
3380#endif
3381}
3382
3383/** sorts linear constraint's variables depending on the stage of the solving process:
3384 * - during PRESOLVING
3385 * sorts variables by binaries, integers, implicit integers, and continuous variables,
3386 * and the variables of the same type by non-decreasing variable index
3387 *
3388 * - during SOLVING
3389 * sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables,
3390 * and binary and integer variables by their global max activity delta (within each group),
3391 * ties within a group are broken by problem index of the variable.
3392 *
3393 * This fastens the propagation time of the constraint handler.
3394 */
3395static
3397 SCIP* scip, /**< SCIP data structure */
3398 SCIP_CONSDATA* consdata /**< linear constraint data */
3399 )
3400{
3401 assert(scip != NULL);
3402 assert(consdata != NULL);
3403
3404 /* check if there are variables for sorting */
3405 if( consdata->nvars <= 1 )
3406 {
3407 consdata->indexsorted = TRUE;
3408 consdata->coefsorted = TRUE;
3409 consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3410 }
3411 else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3412 || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3413 {
3414 int* perm;
3415 int v;
3416
3417 /* get temporary memory to store the sorted permutation */
3418 SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3419
3420 /* call sorting method */
3422 SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3423 else
3424 SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3425
3426 permSortConsdata(consdata, perm, consdata->nvars);
3427
3428 /* free temporary memory */
3429 SCIPfreeBufferArray(scip, &perm);
3430
3432 {
3433 consdata->indexsorted = FALSE;
3434 consdata->coefsorted = TRUE;
3435
3436 /* count binary variables in the sorted vars array */
3437 consdata->nbinvars = 0;
3438 for( v = 0; v < consdata->nvars; ++v )
3439 {
3440 if( SCIPvarIsBinary(consdata->vars[v]) )
3441 ++consdata->nbinvars;
3442 else
3443 break;
3444 }
3445 }
3446 else
3447 {
3448 consdata->indexsorted = TRUE;
3449 consdata->coefsorted = FALSE;
3450 }
3451 }
3452
3453 return SCIP_OKAY;
3454}
3455
3456
3457/*
3458 * local linear constraint handler methods
3459 */
3460
3461/** sets left hand side of linear constraint */
3462static
3464 SCIP* scip, /**< SCIP data structure */
3465 SCIP_CONS* cons, /**< linear constraint */
3466 SCIP_Real lhs /**< new left hand side */
3467 )
3468{
3469 SCIP_CONSDATA* consdata;
3470 SCIP_Bool locked;
3471 int i;
3472
3473 assert(scip != NULL);
3474 assert(cons != NULL);
3475
3476 /* adjust value to be not beyond infinity */
3477 if( SCIPisInfinity(scip, -lhs) )
3478 lhs = -SCIPinfinity(scip);
3479 else if( SCIPisInfinity(scip, lhs) )
3480 lhs = SCIPinfinity(scip);
3481
3482 consdata = SCIPconsGetData(cons);
3483 assert(consdata != NULL);
3484 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3485
3486 /* check whether the side is not changed */
3487 if( SCIPisEQ(scip, consdata->lhs, lhs) )
3488 return SCIP_OKAY;
3489
3490 assert(!SCIPisInfinity(scip, ABS(consdata->lhs)) || !SCIPisInfinity(scip, ABS(lhs)));
3491
3492 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3493 if( SCIPisEQ(scip, lhs, consdata->rhs) )
3494 {
3495 consdata->rhs = lhs;
3496 assert(consdata->row == NULL);
3497 }
3498
3499 locked = FALSE;
3500 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3501 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3502
3503 /* if necessary, update the rounding locks of variables */
3504 if( locked )
3505 {
3506 if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3507 {
3508 SCIP_VAR** vars;
3509 SCIP_Real* vals;
3510 int v;
3511
3512 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3513 vars = consdata->vars;
3514 vals = consdata->vals;
3515
3516 for( v = 0; v < consdata->nvars; ++v )
3517 {
3518 assert(vars[v] != NULL);
3519 assert(!SCIPisZero(scip, vals[v]));
3520
3521 if( SCIPisPositive(scip, vals[v]) )
3522 {
3523 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3524 }
3525 else
3526 {
3527 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3528 }
3529 }
3530 }
3531 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3532 {
3533 SCIP_VAR** vars;
3534 SCIP_Real* vals;
3535 int v;
3536
3537 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3538 vars = consdata->vars;
3539 vals = consdata->vals;
3540
3541 for( v = 0; v < consdata->nvars; ++v )
3542 {
3543 assert(vars[v] != NULL);
3544 assert(!SCIPisZero(scip, vals[v]));
3545
3546 if( SCIPisPositive(scip, vals[v]) )
3547 {
3549 }
3550 else
3551 {
3553 }
3554 }
3555 }
3556 }
3557
3558 /* 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 */
3559 if( !SCIPisInfinity(scip, ABS(lhs)) && SCIPisGT(scip, lhs, consdata->lhs) )
3560 {
3561 consdata->boundstightened = 0;
3562 consdata->presolved = FALSE;
3563 consdata->cliquesadded = FALSE;
3564 consdata->implsadded = FALSE;
3565
3566 /* mark the constraint for propagation */
3567 if( SCIPconsIsTransformed(cons) )
3568 {
3570 }
3571 }
3572
3573 /* set new left hand side and update constraint data */
3574 consdata->lhs = lhs;
3575 consdata->changed = TRUE;
3576 consdata->normalized = FALSE;
3577 consdata->upgradetried = FALSE;
3578 consdata->rangedrowpropagated = 0;
3579
3580 /* update the lhs of the LP row */
3581 if( consdata->row != NULL )
3582 {
3583 SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3584 }
3585
3586 return SCIP_OKAY;
3587}
3588
3589/** sets right hand side of linear constraint */
3590static
3592 SCIP* scip, /**< SCIP data structure */
3593 SCIP_CONS* cons, /**< linear constraint */
3594 SCIP_Real rhs /**< new right hand side */
3595 )
3596{
3597 SCIP_CONSDATA* consdata;
3598 SCIP_Bool locked;
3599 int i;
3600
3601 assert(scip != NULL);
3602 assert(cons != NULL);
3603
3604 /* adjust value to be not beyond infinity */
3605 if( SCIPisInfinity(scip, rhs) )
3606 rhs = SCIPinfinity(scip);
3607 else if( SCIPisInfinity(scip, -rhs) )
3608 rhs = -SCIPinfinity(scip);
3609
3610 consdata = SCIPconsGetData(cons);
3611 assert(consdata != NULL);
3612 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3613
3614 /* check whether the side is not changed */
3615 if( SCIPisEQ(scip, consdata->rhs, rhs) )
3616 return SCIP_OKAY;
3617
3618 assert(!SCIPisInfinity(scip, ABS(consdata->rhs)) || !SCIPisInfinity(scip, ABS(rhs)));
3619
3620 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3621 if( SCIPisEQ(scip, rhs, consdata->lhs) )
3622 {
3623 consdata->lhs = rhs;
3624 assert(consdata->row == NULL);
3625 }
3626
3627 locked = FALSE;
3628 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3629 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3630
3631 /* if necessary, update the rounding locks of variables */
3632 if( locked )
3633 {
3635
3636 if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3637 {
3638 SCIP_VAR** vars;
3639 SCIP_Real* vals;
3640 int v;
3641
3642 /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3643 vars = consdata->vars;
3644 vals = consdata->vals;
3645
3646 for( v = 0; v < consdata->nvars; ++v )
3647 {
3648 assert(vars[v] != NULL);
3649 assert(!SCIPisZero(scip, vals[v]));
3650
3651 if( SCIPisPositive(scip, vals[v]) )
3652 {
3653 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3654 }
3655 else
3656 {
3657 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3658 }
3659 }
3660 }
3661 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3662 {
3663 SCIP_VAR** vars;
3664 SCIP_Real* vals;
3665 int v;
3666
3667 /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3668 vars = consdata->vars;
3669 vals = consdata->vals;
3670
3671 for( v = 0; v < consdata->nvars; ++v )
3672 {
3673 assert(vars[v] != NULL);
3674 assert(!SCIPisZero(scip, vals[v]));
3675
3676 if( SCIPisPositive(scip, vals[v]) )
3677 {
3679 }
3680 else
3681 {
3683 }
3684 }
3685 }
3686 }
3687
3688 /* 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 */
3689 if( !SCIPisInfinity(scip, ABS(rhs)) && SCIPisLT(scip, rhs, consdata->rhs) )
3690 {
3691 consdata->boundstightened = 0;
3692 consdata->presolved = FALSE;
3693 consdata->cliquesadded = FALSE;
3694 consdata->implsadded = FALSE;
3695
3696 /* mark the constraint for propagation */
3697 if( SCIPconsIsTransformed(cons) )
3698 {
3700 }
3701 }
3702
3703 /* set new right hand side and update constraint data */
3704 consdata->rhs = rhs;
3705 consdata->changed = TRUE;
3706 consdata->normalized = FALSE;
3707 consdata->upgradetried = FALSE;
3708 consdata->rangedrowpropagated = 0;
3709
3710 /* update the rhs of the LP row */
3711 if( consdata->row != NULL )
3712 {
3713 SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3714 }
3715
3716 return SCIP_OKAY;
3717}
3718
3719/** adds coefficient in linear constraint */
3720static
3722 SCIP* scip, /**< SCIP data structure */
3723 SCIP_CONS* cons, /**< linear constraint */
3724 SCIP_VAR* var, /**< variable of constraint entry */
3725 SCIP_Real val /**< coefficient of constraint entry */
3726 )
3727{
3728 SCIP_CONSDATA* consdata;
3729 SCIP_Bool transformed;
3730
3731 assert(scip != NULL);
3732 assert(cons != NULL);
3733 assert(var != NULL);
3734
3735 /* relaxation-only variables must not be used in checked or enforced constraints */
3737
3738 /* ignore coefficient if it is nearly zero */
3739 if( SCIPisZero(scip, val) )
3740 return SCIP_OKAY;
3741
3742 consdata = SCIPconsGetData(cons);
3743 assert(consdata != NULL);
3744
3745 /* are we in the transformed problem? */
3746 transformed = SCIPconsIsTransformed(cons);
3747
3748 /* always use transformed variables in transformed constraints */
3749 if( transformed )
3750 {
3752 }
3753 assert(var != NULL);
3754 assert(transformed == SCIPvarIsTransformed(var));
3755
3756 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3757 consdata->vars[consdata->nvars] = var;
3758 consdata->vals[consdata->nvars] = val;
3759 consdata->nvars++;
3760
3761 /* capture variable */
3763
3764 /* if we are in transformed problem, the variable needs an additional event data */
3765 if( transformed )
3766 {
3767 if( consdata->eventdata != NULL )
3768 {
3769 SCIP_CONSHDLR* conshdlr;
3770 SCIP_CONSHDLRDATA* conshdlrdata;
3771
3772 /* check for event handler */
3773 conshdlr = SCIPconsGetHdlr(cons);
3774 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3775 assert(conshdlrdata != NULL);
3776 assert(conshdlrdata->eventhdlr != NULL);
3777
3778 /* initialize eventdata array */
3779 consdata->eventdata[consdata->nvars-1] = NULL;
3780
3781 /* catch bound change events of variable */
3782 SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3783 }
3784
3785 /* update minimum and maximum activities */
3786 consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3787
3788 /* update maximum activity delta */
3789 if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3790 {
3791 SCIP_Real lb;
3792 SCIP_Real ub;
3793
3794 lb = SCIPvarGetLbLocal(var);
3795 ub = SCIPvarGetUbLocal(var);
3796
3797 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3798 {
3799 consdata->maxactdelta = SCIPinfinity(scip);
3800 consdata->maxactdeltavar = var;
3801 }
3802 else
3803 {
3804 SCIP_Real domain = ub - lb;
3805 SCIP_Real delta = REALABS(val) * domain;
3806
3807 if( delta > consdata->maxactdelta )
3808 {
3809 consdata->maxactdelta = delta;
3810 consdata->maxactdeltavar = var;
3811 }
3812 }
3813 }
3814 }
3815
3816 /* install rounding locks for new variable */
3817 SCIP_CALL( lockRounding(scip, cons, var, val) );
3818
3819 /* mark the constraint for propagation */
3820 if( transformed )
3821 {
3823 }
3824
3825 consdata->boundstightened = 0;
3826 consdata->presolved = FALSE;
3827 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3828
3829 if( consdata->validsignature )
3830 consdataUpdateSignatures(consdata, consdata->nvars-1);
3831
3832 consdata->changed = TRUE;
3833 consdata->normalized = FALSE;
3834 consdata->upgradetried = FALSE;
3835 consdata->cliquesadded = FALSE;
3836 consdata->implsadded = FALSE;
3837 consdata->rangedrowpropagated = 0;
3838
3839 if( consdata->nvars == 1 )
3840 {
3841 consdata->indexsorted = TRUE;
3842 consdata->coefsorted = TRUE;
3843 consdata->merged = TRUE;
3844 }
3845 else
3846 {
3847 consdata->merged = FALSE;
3848
3850 {
3851 consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3852 consdata->coefsorted = FALSE;
3853 }
3854 else
3855 {
3856 consdata->indexsorted = FALSE;
3857 consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3858 }
3859 }
3860
3861 /* update hascontvar and hasnonbinvar flags */
3862 if( consdata->hasnonbinvalid && !consdata->hascontvar )
3863 {
3864 SCIP_VARTYPE vartype = SCIPvarGetType(var);
3865
3866 if( vartype != SCIP_VARTYPE_BINARY )
3867 {
3868 consdata->hasnonbinvar = TRUE;
3869
3870 if( vartype == SCIP_VARTYPE_CONTINUOUS )
3871 consdata->hascontvar = TRUE;
3872 }
3873 }
3874
3875 /* add the new coefficient to the LP row */
3876 if( consdata->row != NULL )
3877 {
3878 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3879 }
3880
3881 return SCIP_OKAY;
3882}
3883
3884/** deletes coefficient at given position from linear constraint data */
3885static
3887 SCIP* scip, /**< SCIP data structure */
3888 SCIP_CONS* cons, /**< linear constraint */
3889 int pos /**< position of coefficient to delete */
3890 )
3891{
3892 SCIP_CONSDATA* consdata;
3893 SCIP_VAR* var;
3894 SCIP_Real val;
3895
3896 assert(scip != NULL);
3897 assert(cons != NULL);
3898
3899 consdata = SCIPconsGetData(cons);
3900 assert(consdata != NULL);
3901 assert(0 <= pos && pos < consdata->nvars);
3902
3903 var = consdata->vars[pos];
3904 val = consdata->vals[pos];
3905 assert(var != NULL);
3906
3907 /* remove rounding locks for deleted variable */
3908 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3909
3910 /* if we are in transformed problem, delete the event data of the variable */
3911 if( SCIPconsIsTransformed(cons) )
3912 {
3913 SCIP_CONSHDLR* conshdlr;
3914 SCIP_CONSHDLRDATA* conshdlrdata;
3915
3916 /* check for event handler */
3917 conshdlr = SCIPconsGetHdlr(cons);
3918 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3919 assert(conshdlrdata != NULL);
3920 assert(conshdlrdata->eventhdlr != NULL);
3921
3922 /* drop bound change events of variable */
3923 if( consdata->eventdata != NULL )
3924 {
3925 SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3926 assert(consdata->eventdata[pos] == NULL);
3927 }
3928 }
3929
3930 /* move the last variable to the free slot */
3931 if( pos != consdata->nvars - 1 )
3932 {
3933 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3934 consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3935
3936 if( consdata->eventdata != NULL )
3937 {
3938 consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3939 assert(consdata->eventdata[pos] != NULL);
3940 consdata->eventdata[pos]->varpos = pos;
3941 }
3942
3943 consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3944 consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3945 }
3946 consdata->nvars--;
3947
3948 /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3949 * of the remaining variable, or give exactly 0.0)
3950 */
3951 if( consdata->nvars <= 1 )
3953 else
3954 {
3955 if( SCIPconsIsTransformed(cons) )
3956 {
3957 /* if we are in transformed problem, update minimum and maximum activities */
3958 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3959
3960 /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3961 * delta needs to be recalculated on the next real propagation
3962 */
3963 if( consdata->maxactdeltavar == var )
3964 {
3965 consdata->maxactdelta = SCIP_INVALID;
3966 consdata->maxactdeltavar = NULL;
3967 }
3968 }
3969 }
3970
3971 /* mark the constraint for propagation */
3972 if( SCIPconsIsTransformed(cons) )
3973 {
3975 }
3976
3977 consdata->boundstightened = 0;
3978 consdata->presolved = FALSE;
3979 consdata->validsignature = FALSE;
3980 consdata->changed = TRUE;
3981 consdata->normalized = FALSE;
3982 consdata->upgradetried = FALSE;
3983 consdata->cliquesadded = FALSE;
3984 consdata->implsadded = FALSE;
3985 consdata->rangedrowpropagated = 0;
3986
3987 /* check if hasnonbinvar flag might be incorrect now */
3988 if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3989 {
3990 consdata->hasnonbinvalid = FALSE;
3991 }
3992
3993 /* delete coefficient from the LP row */
3994 if( consdata->row != NULL )
3995 {
3996 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3997 }
3998
3999 /* release variable */
4001
4002 return SCIP_OKAY;
4003}
4004
4005/** changes coefficient value at given position of linear constraint data */
4006static
4008 SCIP* scip, /**< SCIP data structure */
4009 SCIP_CONS* cons, /**< linear constraint */
4010 int pos, /**< position of coefficient to delete */
4011 SCIP_Real newval /**< new value of coefficient */
4012 )
4013{
4014 SCIP_CONSDATA* consdata;
4015 SCIP_VAR* var;
4016 SCIP_Real val;
4017 SCIP_Bool locked;
4018 int i;
4019
4020 assert(scip != NULL);
4021 assert(cons != NULL);
4022 assert(!SCIPisZero(scip, newval));
4023
4024 consdata = SCIPconsGetData(cons);
4025 assert(consdata != NULL);
4026 assert(0 <= pos && pos < consdata->nvars);
4027 assert(!SCIPisZero(scip, newval));
4028
4029 var = consdata->vars[pos];
4030 val = consdata->vals[pos];
4031 assert(var != NULL);
4033
4034 locked = FALSE;
4035 for( i = 0; i < NLOCKTYPES && !locked; i++ )
4036 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
4037
4038 /* if necessary, update the rounding locks of the variable */
4039 if( locked && newval * val < 0.0 )
4040 {
4042
4043 /* remove rounding locks for variable with old coefficient */
4044 SCIP_CALL( unlockRounding(scip, cons, var, val) );
4045
4046 /* install rounding locks for variable with new coefficient */
4047 SCIP_CALL( lockRounding(scip, cons, var, newval) );
4048 }
4049
4050 /* change the value */
4051 consdata->vals[pos] = newval;
4052
4053 if( consdata->coefsorted )
4054 {
4055 if( pos > 0 )
4056 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
4057 if( consdata->coefsorted && pos < consdata->nvars - 1 )
4058 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
4059 }
4060
4061 /* update minimum and maximum activities */
4062 if( SCIPconsIsTransformed(cons) )
4063 consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
4064
4065 /* mark the constraint for propagation */
4066 if( SCIPconsIsTransformed(cons) )
4067 {
4069 }
4070
4071 consdata->boundstightened = 0;
4072 consdata->presolved = FALSE;
4073 consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
4074 consdata->changed = TRUE;
4075 consdata->normalized = FALSE;
4076 consdata->upgradetried = FALSE;
4077 consdata->cliquesadded = FALSE;
4078 consdata->implsadded = FALSE;
4079 consdata->rangedrowpropagated = 0;
4080
4081 return SCIP_OKAY;
4082}
4083
4084/** scales a linear constraint with a constant scalar */
4085static
4087 SCIP* scip, /**< SCIP data structure */
4088 SCIP_CONS* cons, /**< linear constraint to scale */
4089 SCIP_Real scalar /**< value to scale constraint with */
4090 )
4091{
4092 SCIP_CONSDATA* consdata;
4093 SCIP_Real newval;
4094 SCIP_Real absscalar;
4095 int i;
4096
4097 assert(scip != NULL);
4098 assert(cons != NULL);
4099
4100 consdata = SCIPconsGetData(cons);
4101 assert(consdata != NULL);
4102 assert(consdata->row == NULL);
4103 assert(scalar != 1.0);
4104
4105 if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4106 || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4107 {
4108 SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4109 SCIPconsGetName(cons), scalar);
4110
4111 return SCIP_OKAY;
4112 }
4113
4114 /* scale the coefficients */
4115 for( i = consdata->nvars - 1; i >= 0; --i )
4116 {
4117 newval = scalar * consdata->vals[i];
4118
4119 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4120 * flooring down our new value
4121 */
4122 if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4123 newval = SCIPfeasFloor(scip, newval + 0.5);
4124
4125 if( SCIPisZero(scip, newval) )
4126 {
4127 SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4128 consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4129 SCIP_CALL( delCoefPos(scip, cons, i) );
4130 }
4131 else
4132 consdata->vals[i] = newval;
4133 }
4134
4135 /* scale the sides */
4136 if( scalar < 0.0 )
4137 {
4138 SCIP_Real lhs;
4139
4140 lhs = consdata->lhs;
4141 consdata->lhs = -consdata->rhs;
4142 consdata->rhs = -lhs;
4143 }
4144 absscalar = REALABS(scalar);
4145 if( !SCIPisInfinity(scip, -consdata->lhs) )
4146 {
4147 newval = absscalar * consdata->lhs;
4148
4149 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4150 * flooring down our new value
4151 */
4152 if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4153 consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4154 else
4155 consdata->lhs = newval;
4156 }
4157 if( !SCIPisInfinity(scip, consdata->rhs) )
4158 {
4159 newval = absscalar * consdata->rhs;
4160
4161 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4162 * our new value
4163 */
4164 if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4165 consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4166 else
4167 consdata->rhs = newval;
4168 }
4169
4171 consdata->cliquesadded = FALSE;
4172 consdata->implsadded = FALSE;
4173
4174 return SCIP_OKAY;
4175}
4176
4177/** perform deletion of variables in all constraints of the constraint handler */
4178static
4180 SCIP* scip, /**< SCIP data structure */
4181 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4182 SCIP_CONS** conss, /**< array of constraints */
4183 int nconss /**< number of constraints */
4184 )
4185{
4186 SCIP_CONSDATA* consdata;
4187 int i;
4188 int v;
4189
4190 assert(scip != NULL);
4191 assert(conshdlr != NULL);
4192 assert(conss != NULL);
4193 assert(nconss >= 0);
4194 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4195
4196 /* iterate over all constraints */
4197 for( i = 0; i < nconss; i++ )
4198 {
4199 consdata = SCIPconsGetData(conss[i]);
4200
4201 /* constraint is marked, that some of its variables were deleted */
4202 if( consdata->varsdeleted )
4203 {
4204 /* iterate over all variables of the constraint and delete them from the constraint */
4205 for( v = consdata->nvars - 1; v >= 0; --v )
4206 {
4207 if( SCIPvarIsDeleted(consdata->vars[v]) )
4208 {
4209 SCIP_CALL( delCoefPos(scip, conss[i], v) );
4210 }
4211 }
4212 consdata->varsdeleted = FALSE;
4213 }
4214 }
4215
4216 return SCIP_OKAY;
4217}
4218
4219
4220/** normalizes a linear constraint with the following rules:
4221 * - if all coefficients have them same absolute value, change them to (-)1.0
4222 * - multiplication with +1 or -1:
4223 * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4224 * if the current rule doesn't determine the sign):
4225 * 1. the right hand side must not be negative
4226 * 2. the right hand side must not be infinite
4227 * 3. the absolute value of the right hand side must be greater than that of the left hand side
4228 * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4229 * 5. multiply with +1
4230 * - rationals to integrals
4231 * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4232 * by the smallest common multiple of all denominators to get integral coefficients.
4233 * Forbid large denominators due to numerical stability.
4234 * - division by greatest common divisor
4235 * If all coefficients are integral, divide them by the greatest common divisor.
4236 */
4237static
4239 SCIP* scip, /**< SCIP data structure */
4240 SCIP_CONS* cons, /**< linear constraint to normalize */
4241 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4242 )
4243{
4244 SCIP_CONSDATA* consdata;
4245 SCIP_Real* vals;
4246 SCIP_Longint scm;
4247 SCIP_Longint nominator;
4248 SCIP_Longint denominator;
4249 SCIP_Longint gcd;
4250 SCIP_Longint maxmult;
4251 SCIP_Real epsilon;
4252 SCIP_Real feastol;
4253 SCIP_Real maxabsval;
4254 SCIP_Real minabsval;
4255 SCIP_Bool success;
4256 SCIP_Bool onlyintegral;
4257 int nvars;
4258 int mult;
4259 int nposcoeffs;
4260 int nnegcoeffs;
4261 int i;
4262
4263 assert(scip != NULL);
4264 assert(cons != NULL);
4265 assert(infeasible != NULL);
4266
4267 *infeasible = FALSE;
4268
4269 /* we must not change a modifiable constraint in any way */
4270 if( SCIPconsIsModifiable(cons) )
4271 return SCIP_OKAY;
4272
4273 /* get constraint data */
4274 consdata = SCIPconsGetData(cons);
4275 assert(consdata != NULL);
4276
4277 /* check, if the constraint is already normalized */
4278 if( consdata->normalized )
4279 return SCIP_OKAY;
4280
4281 /* get coefficient arrays */
4282 vals = consdata->vals;
4283 nvars = consdata->nvars;
4284 assert(nvars == 0 || vals != NULL);
4285
4286 if( nvars == 0 )
4287 {
4288 consdata->normalized = TRUE;
4289 return SCIP_OKAY;
4290 }
4291
4292 assert(vals != NULL);
4293
4294 /* get maximum and minimum absolute coefficient */
4295 maxabsval = consdataGetMaxAbsval(consdata);
4296 minabsval = consdataGetMinAbsval(consdata);
4297
4298 /* return if scaling by maxval will eliminate coefficients */
4299 if( SCIPisZero(scip, minabsval/maxabsval) )
4300 return SCIP_OKAY;
4301
4302 /* return if scaling by maxval will eliminate or generate non-zero sides */
4303 if( !SCIPisInfinity(scip, consdata->lhs) && SCIPisFeasZero(scip, consdata->lhs) != SCIPisFeasZero(scip, consdata->lhs/maxabsval) )
4304 return SCIP_OKAY;
4305 if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasZero(scip, consdata->rhs) != SCIPisFeasZero(scip, consdata->rhs/maxabsval) )
4306 return SCIP_OKAY;
4307
4308 /* check if not all absolute coefficients are near 1.0 but scaling could do */
4309 if( SCIPisLT(scip, minabsval, 1.0) != SCIPisGT(scip, maxabsval, 1.0) )
4310 {
4311 SCIP_Real scalar;
4312
4313 /* calculate scale of the average minimum and maximum absolute coefficient to 1.0 */
4314 scalar = 2.0 / (minabsval + maxabsval);
4315
4316 /* check if all scaled absolute coefficients are near 1.0
4317 * we can relax EQ(x,1.0) to LE(x,1.0), as LT(x,1.0) is not possible
4318 */
4319 if( SCIPisLE(scip, scalar * maxabsval, 1.0) )
4320 {
4321 SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4323 SCIP_CALL( scaleCons(scip, cons, scalar) );
4324
4325 /* get new consdata information, because scaleCons() might have deleted variables */
4326 vals = consdata->vals;
4327 nvars = consdata->nvars;
4328
4329 assert(nvars == 0 || vals != NULL);
4330 }
4331 }
4332
4333 /* nvars might have changed */
4334 if( nvars == 0 )
4335 {
4336 consdata->normalized = TRUE;
4337 return SCIP_OKAY;
4338 }
4339
4340 assert(vals != NULL);
4341
4342 /* calculate the maximal multiplier for common divisor calculation:
4343 * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4344 * which means, a value of feastol/epsilon should be used as maximal multiplier;
4345 * additionally, we don't want to scale the constraint if this would lead to too
4346 * large coefficients
4347 */
4348 epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4349 feastol = SCIPfeastol(scip);
4350 maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4351
4352 if( !consdata->hasnonbinvalid )
4353 consdataCheckNonbinvar(consdata);
4354
4355 /* get maximum absolute coefficient */
4356 maxabsval = consdataGetMaxAbsval(consdata);
4357
4358 /* if all variables are of integral type we will allow a greater multiplier */
4359 if( !consdata->hascontvar )
4360 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4361 else
4362 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4363
4364 /*
4365 * multiplication with +1 or -1
4366 */
4367 mult = 0;
4368
4369 /* 1. the right hand side must not be negative */
4370 if( SCIPisPositive(scip, consdata->lhs) )
4371 mult = +1;
4372 else if( SCIPisNegative(scip, consdata->rhs) )
4373 mult = -1;
4374
4375 if( mult == 0 )
4376 {
4377 /* 2. the right hand side must not be infinite */
4378 if( SCIPisInfinity(scip, -consdata->lhs) )
4379 mult = +1;
4380 else if( SCIPisInfinity(scip, consdata->rhs) )
4381 mult = -1;
4382 }
4383
4384 if( mult == 0 )
4385 {
4386 /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4387 if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4388 mult = +1;
4389 else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4390 mult = -1;
4391 }
4392
4393 if( mult == 0 )
4394 {
4395 /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4396 nposcoeffs = 0;
4397 nnegcoeffs = 0;
4398 for( i = 0; i < nvars; ++i )
4399 {
4400 if( vals[i] > 0.0 )
4401 nposcoeffs++;
4402 else
4403 nnegcoeffs++;
4404 }
4405 if( nposcoeffs > nnegcoeffs )
4406 mult = +1;
4407 else if( nposcoeffs < nnegcoeffs )
4408 mult = -1;
4409 }
4410
4411 if( mult == 0 )
4412 {
4413 /* 5. multiply with +1 */
4414 mult = +1;
4415 }
4416
4417 assert(mult == +1 || mult == -1);
4418 if( mult == -1 )
4419 {
4420 /* scale the constraint with -1 */
4421 SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4423 SCIP_CALL( scaleCons(scip, cons, -1.0) );
4424
4425 /* scalecons() can delete variables, but scaling with -1 should not do that */
4426 assert(nvars == consdata->nvars);
4427 }
4428
4429 /*
4430 * rationals to integrals
4431 *
4432 * @todo try scaling only on behalf of non-continuous variables
4433 */
4434 success = TRUE;
4435 scm = 1;
4436 for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4437 {
4438 if( !SCIPisIntegral(scip, vals[i]) )
4439 {
4440 /* epsilon has been slightly decreased above - to be on the safe side */
4441 success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4442 if( success )
4443 scm = SCIPcalcSmaComMul(scm, denominator);
4444 }
4445 }
4446 assert(scm >= 1);
4447
4448 /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4449 * their greatest common divisor
4450 */
4451 onlyintegral = TRUE;
4452 if( scm == 1 )
4453 {
4454 for( i = nvars - 1; i >= 0; --i )
4455 {
4456 if( !SCIPisIntegral(scip, vals[i]) )
4457 {
4458 onlyintegral = FALSE;
4459 break;
4460 }
4461 }
4462 }
4463
4464 success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4465 if( success && scm != 1 )
4466 {
4467 /* scale the constraint with the smallest common multiple of all denominators */
4468 SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4470 SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4471
4472 if( consdata->validmaxabsval )
4473 {
4474 consdata->maxabsval *= REALABS((SCIP_Real)scm);
4475 if( !SCIPisIntegral(scip, consdata->maxabsval) )
4476 {
4477 consdata->validmaxabsval = FALSE;
4478 consdata->maxabsval = SCIP_INVALID;
4479 consdataCalcMaxAbsval(consdata);
4480 }
4481 }
4482
4483 if( consdata->validminabsval )
4484 {
4485 consdata->minabsval *= REALABS((SCIP_Real)scm);
4486 if( !SCIPisIntegral(scip, consdata->minabsval) )
4487 {
4488 consdata->validminabsval = FALSE;
4489 consdata->minabsval = SCIP_INVALID;
4490 consdataCalcMinAbsval(consdata);
4491 }
4492 }
4493
4494 /* get new consdata information, because scalecons() might have deleted variables */
4495 vals = consdata->vals;
4496 nvars = consdata->nvars;
4497 assert(nvars == 0 || vals != NULL);
4498 }
4499
4500 /*
4501 * division by greatest common divisor
4502 */
4503 if( success && nvars >= 1 )
4504 {
4505 /* all coefficients are integral: divide them by their greatest common divisor */
4506 assert(SCIPisIntegral(scip, vals[0]));
4507
4508 gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4509 for( i = 1; i < nvars && gcd > 1; ++i )
4510 {
4511 assert(SCIPisIntegral(scip, vals[i]));
4512 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4513 }
4514
4515 if( gcd > 1 )
4516 {
4517 /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4518 if( !consdata->hascontvar && onlyintegral )
4519 {
4520 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4521 {
4522 *infeasible = TRUE;
4523
4524 SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4526
4527 return SCIP_OKAY;
4528 }
4529 }
4530
4531 /* divide the constraint by the greatest common divisor of the coefficients */
4532 SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4534 SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4535
4536 if( consdata->validmaxabsval )
4537 {
4538 consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4539 }
4540 if( consdata->validminabsval )
4541 {
4542 consdata->minabsval /= REALABS((SCIP_Real)gcd);
4543 }
4544 }
4545 }
4546
4547 /* mark constraint to be normalized */
4548 consdata->normalized = TRUE;
4549
4550 SCIPdebugMsg(scip, "normalized constraint:\n");
4552
4553 return SCIP_OKAY;
4554}
4555
4556/** replaces multiple occurrences of a variable by a single coefficient */
4557static
4559 SCIP* scip, /**< SCIP data structure */
4560 SCIP_CONS* cons /**< linear constraint */
4561 )
4562{
4563 SCIP_CONSDATA* consdata;
4564 SCIP_VAR* var;
4565 SCIP_Real valsum;
4566 int v;
4567
4568 assert(scip != NULL);
4569 assert(cons != NULL);
4570
4571 consdata = SCIPconsGetData(cons);
4572 assert(consdata != NULL);
4573
4574 if( consdata->merged )
4575 return SCIP_OKAY;
4576
4577 /* sort the constraint */
4578 SCIP_CALL( consdataSort(scip, consdata) );
4579
4580 /* go backwards through the constraint looking for multiple occurrences of the same variable;
4581 * backward direction is necessary, since delCoefPos() modifies the given position and
4582 * the subsequent ones
4583 */
4584 v = consdata->nvars-1;
4585 while( v >= 1 )
4586 {
4587 var = consdata->vars[v];
4588 if( consdata->vars[v-1] == var )
4589 {
4590 valsum = consdata->vals[v];
4591 do
4592 {
4593 SCIP_CALL( delCoefPos(scip, cons, v) );
4594 --v;
4595 valsum += consdata->vals[v];
4596 }
4597 while( v >= 1 && consdata->vars[v-1] == var );
4598
4599 /* modify the last existing occurrence of the variable */
4600 assert(consdata->vars[v] == var);
4601 if( SCIPisZero(scip, valsum) )
4602 {
4603 SCIP_CALL( delCoefPos(scip, cons, v) );
4604
4605 /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4606 * delta needs to be recalculated on the next real propagation
4607 */
4608 if( consdata->maxactdeltavar == var )
4609 {
4610 consdata->maxactdelta = SCIP_INVALID;
4611 consdata->maxactdeltavar = NULL;
4612 }
4613 }
4614 else
4615 {
4616 SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4617 }
4618 }
4619 --v;
4620 }
4621
4622 consdata->merged = TRUE;
4623
4624 return SCIP_OKAY;
4625}
4626
4627/** replaces all fixed and aggregated variables by their non-fixed counterparts */
4628static
4630 SCIP* scip, /**< SCIP data structure */
4631 SCIP_CONS* cons, /**< linear constraint */
4632 SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4633 * information is not needed; in this case, we apply all fixings
4634 * instead of stopping after the first infeasible one */
4635 )
4636{
4637 SCIP_CONSDATA* consdata;
4638 SCIP_VAR* var;
4639 SCIP_VAR** aggrvars;
4640 SCIP_Real val;
4641 SCIP_Real* aggrscalars;
4642 SCIP_Real fixedval;
4643 SCIP_Real aggrconst;
4644 int v;
4645 int naggrvars;
4646 int i;
4647
4648 assert(scip != NULL);
4649 assert(cons != NULL);
4650
4651 if( infeasible != NULL )
4652 *infeasible = FALSE;
4653
4654 consdata = SCIPconsGetData(cons);
4655 assert(consdata != NULL);
4656
4657 if( consdata->eventdata == NULL )
4658 {
4659 SCIP_CONSHDLR* conshdlr;
4660 SCIP_CONSHDLRDATA* conshdlrdata;
4661
4662 conshdlr = SCIPconsGetHdlr(cons);
4663 assert(conshdlr != NULL);
4664
4665 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4666 assert(conshdlrdata != NULL);
4667
4668 /* catch bound change events of variables */
4669 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4670 assert(consdata->eventdata != NULL);
4671 }
4672
4673 if( !consdata->removedfixings )
4674 {
4675 SCIP_Real lhssubtrahend;
4676 SCIP_Real rhssubtrahend;
4677
4678 /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4679 * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4680 */
4681 assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4682
4683 lhssubtrahend = 0.0;
4684 rhssubtrahend = 0.0;
4685
4686 SCIPdebugMsg(scip, "applying fixings:\n");
4688
4689 v = 0;
4690 while( v < consdata->nvars )
4691 {
4692 var = consdata->vars[v];
4693 val = consdata->vals[v];
4695
4696 switch( SCIPvarGetStatus(var) )
4697 {
4699 SCIPerrorMessage("original variable in transformed linear constraint\n");
4700 return SCIP_INVALIDDATA;
4701
4704 ++v;
4705 break;
4706
4709 fixedval = SCIPvarGetLbGlobal(var);
4710 if( !SCIPisInfinity(scip, -consdata->lhs) )
4711 {
4712 if( SCIPisInfinity(scip, ABS(fixedval)) )
4713 {
4714 /* if lhs gets infinity it means that the problem is infeasible */
4715 if( ( val > 0.0 ) != ( fixedval > 0.0 ) )
4716 {
4718
4719 if( infeasible != NULL )
4720 {
4721 *infeasible = TRUE;
4722 return SCIP_OKAY;
4723 }
4724 }
4725 else
4726 {
4727 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4728 }
4729 }
4730 else
4731 lhssubtrahend += val * fixedval;
4732 }
4733 if( !SCIPisInfinity(scip, consdata->rhs) )
4734 {
4735 if( SCIPisInfinity(scip, ABS(fixedval)) )
4736 {
4737 /* if rhs gets -infinity it means that the problem is infeasible */
4738 if( ( val > 0.0 ) == ( fixedval > 0.0 ) )
4739 {
4740 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4741
4742 if( infeasible != NULL )
4743 {
4744 *infeasible = TRUE;
4745 return SCIP_OKAY;
4746 }
4747 }
4748 else
4749 {
4751 }
4752 }
4753 else
4754 rhssubtrahend += val * fixedval;
4755 }
4756 SCIP_CALL( delCoefPos(scip, cons, v) );
4757 break;
4758
4760 {
4761 SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4762 SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4763 SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4764
4765 assert(activevar != NULL);
4766 SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4767 assert(activevar != NULL);
4768
4769 if( !SCIPisZero(scip, activescalar) )
4770 {
4771 SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4772 }
4773
4774 if( !SCIPisZero(scip, activeconstant) )
4775 {
4776 if( !SCIPisInfinity(scip, -consdata->lhs) )
4777 lhssubtrahend += activeconstant;
4778 if( !SCIPisInfinity(scip, consdata->rhs) )
4779 rhssubtrahend += activeconstant;
4780 }
4781
4782 SCIP_CALL( delCoefPos(scip, cons, v) );
4783 break;
4784 }
4787 naggrvars = SCIPvarGetMultaggrNVars(var);
4788 aggrvars = SCIPvarGetMultaggrVars(var);
4789 aggrscalars = SCIPvarGetMultaggrScalars(var);
4790 for( i = 0; i < naggrvars; ++i )
4791 {
4792 SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4793 }
4794 aggrconst = SCIPvarGetMultaggrConstant(var);
4795
4796 if( !SCIPisInfinity(scip, -consdata->lhs) )
4797 lhssubtrahend += val * aggrconst;
4798 if( !SCIPisInfinity(scip, consdata->rhs) )
4799 rhssubtrahend += val * aggrconst;
4800
4801 SCIP_CALL( delCoefPos(scip, cons, v) );
4802 break;
4803
4806 aggrconst = SCIPvarGetNegationConstant(var);
4807
4808 if( !SCIPisInfinity(scip, -consdata->lhs) )
4809 lhssubtrahend += val * aggrconst;
4810 if( !SCIPisInfinity(scip, consdata->rhs) )
4811 rhssubtrahend += val * aggrconst;
4812
4813 SCIP_CALL( delCoefPos(scip, cons, v) );
4814 break;
4815
4816 default:
4817 SCIPerrorMessage("unknown variable status\n");
4818 SCIPABORT();
4819 return SCIP_INVALIDDATA; /*lint !e527*/
4820 }
4821 }
4822
4823 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4824 {
4825 /* check left hand side of unmodifiable empty constraint with former feasibility tolerance */
4826 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4827 {
4828 if( SCIPisFeasLT(scip, lhssubtrahend, consdata->lhs) )
4829 {
4831
4832 if( infeasible != NULL )
4833 {
4834 *infeasible = TRUE;
4835 return SCIP_OKAY;
4836 }
4837 }
4838 else
4839 {
4840 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4841 }
4842 }
4843 /* for large numbers that are relatively equal, subtraction can lead to cancellation,
4844 * causing wrong fixings of other variables --> better use a real zero here
4845 */
4846 else if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) )
4847 {
4848 SCIP_CALL( chgLhs(scip, cons, 0.0) );
4849 }
4850 else
4851 {
4852 SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4853 }
4854 }
4855 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs) )
4856 {
4857 /* check right hand side of unmodifiable empty constraint with former feasibility tolerance */
4858 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4859 {
4860 if( SCIPisFeasGT(scip, rhssubtrahend, consdata->rhs) )
4861 {
4862 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4863
4864 if( infeasible != NULL )
4865 {
4866 *infeasible = TRUE;
4867 return SCIP_OKAY;
4868 }
4869 }
4870 else
4871 {
4873 }
4874 }
4875 /* for large numbers that are relatively equal, substraction can lead to cancellation,
4876 * causing wrong fixings of other variables --> better use a real zero here
4877 */
4878 else if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs) )
4879 {
4880 SCIP_CALL( chgRhs(scip, cons, 0.0) );
4881 }
4882 else
4883 {
4884 SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4885 }
4886 }
4887 consdata->removedfixings = TRUE;
4888
4889 SCIPdebugMsg(scip, "after fixings:\n");
4891
4892 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4893 * to clean up the constraint
4894 */
4895 SCIP_CALL( mergeMultiples(scip, cons) );
4896
4897 SCIPdebugMsg(scip, "after merging:\n");
4899 }
4900 assert(consdata->removedfixings);
4901
4902#ifndef NDEBUG
4903 /* check, if all fixings are applied */
4904 for( v = 0; v < consdata->nvars; ++v )
4905 assert(SCIPvarIsActive(consdata->vars[v]));
4906#endif
4907
4908 return SCIP_OKAY;
4909}
4910
4911/** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4912 * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4913 * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4914 * conflict detecting constraint by using NULL as inferred variable
4915 */
4916static
4918 SCIP* scip, /**< SCIP data structure */
4919 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4920 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4921 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4922 int inferpos, /**< position of the inferred variable in the vars array */
4923 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4924 )
4925{
4926 SCIP_CONSDATA* consdata;
4927 SCIP_VAR** vars;
4928 SCIP_Real* vals;
4929 int nvars;
4930 int i;
4931
4932 assert(scip != NULL);
4933 assert(cons != NULL);
4934
4935 consdata = SCIPconsGetData(cons);
4936
4937 assert(consdata != NULL);
4938
4939 vars = consdata->vars;
4940 vals = consdata->vals;
4941 nvars = consdata->nvars;
4942
4943 assert(vars != NULL || nvars == 0);
4944 assert(vals != NULL || nvars == 0);
4945
4946 assert(-1 <= inferpos && inferpos < nvars);
4947 assert((infervar == NULL) == (inferpos == -1));
4948 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4949
4950 /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4951 * residual value, depending on whether the left or right hand side is responsible for the bound change:
4952 * - if the right hand side is the reason, the minimal residual activity is responsible
4953 * - if the left hand side is the reason, the maximal residual activity is responsible
4954 */
4955
4956 /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4957 if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4958 {
4959 SCIP_Real minresactivity;
4960 SCIP_Real maxresactivity;
4961 SCIP_Bool ismintight;
4962 SCIP_Bool ismaxtight;
4963 SCIP_Bool isminsettoinfinity;
4964 SCIP_Bool ismaxsettoinfinity;
4965
4966 minresactivity = -SCIPinfinity(scip);
4967 maxresactivity = SCIPinfinity(scip);
4968
4969 /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4970 if( infervar != NULL )
4971 {
4972 assert(vals != NULL); /* for flexelint */
4973 if( reasonisrhs )
4974 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4975 &ismintight, NULL, &isminsettoinfinity, NULL);
4976 else
4977 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4978 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4979 }
4980 else
4981 {
4982 if( reasonisrhs )
4983 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4984 &ismintight, NULL, &isminsettoinfinity, NULL);
4985 else
4986 consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4987 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4988 }
4989
4990 /* we can only do something clever, if the residual activity is finite and not relaxed */
4991 if( (reasonisrhs && !isminsettoinfinity && ismintight) || (!reasonisrhs && !ismaxsettoinfinity && ismaxtight) ) /*lint !e644*/
4992 {
4993 SCIP_Real rescap;
4994 SCIP_Bool resactisinf;
4995
4996 resactisinf = FALSE;
4997
4998 /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4999 * than its inferred bound
5000 */
5001 if( infervar != NULL )
5002 {
5003 assert(vals != NULL); /* for flexelint */
5004
5005 if( reasonisrhs )
5006 {
5007 if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
5008 {
5009 consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
5010 if( SCIPisInfinity(scip, -minresactivity) )
5011 resactisinf = TRUE;
5012 }
5013 rescap = consdata->rhs - minresactivity;
5014 }
5015 else
5016 {
5017 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
5018 {
5019 consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
5020 if( SCIPisInfinity(scip, maxresactivity) )
5021 resactisinf = TRUE;
5022 }
5023 rescap = consdata->lhs - maxresactivity;
5024 }
5025
5026 if( reasonisrhs == (vals[inferpos] > 0.0) )
5027 rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
5028 else
5029 rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
5030 }
5031 else
5032 rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
5033
5034 if( !resactisinf )
5035 {
5036 /* now add bounds as reasons until the residual capacity is exceeded */
5037 for( i = 0; i < nvars; ++i )
5038 {
5039 assert( vars != NULL && vals != NULL ); /* for lint */
5040
5041 /* zero coefficients and the inferred variable can be ignored */
5042 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5043 continue;
5044
5045 /* check if the residual capacity is exceeded */
5046 if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
5047 || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
5048 break;
5049
5050 /* update the residual capacity due to the local bound of this variable */
5051 if( reasonisrhs == (vals[i] > 0.0) )
5052 {
5053 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
5054 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5055 rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
5056 }
5057 else
5058 {
5059 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
5060 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5061 rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
5062 }
5063 }
5064 return SCIP_OKAY;
5065 }
5066 }
5067 }
5068
5069 /* for a bound change on a continuous variable, all locally changed bounds are responsible */
5070 for( i = 0; i < nvars; ++i )
5071 {
5072 assert(vars != NULL); /* for flexelint */
5073 assert(vals != NULL); /* for flexelint */
5074
5075 /* zero coefficients and the inferred variable can be ignored */
5076 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5077 continue;
5078
5079 if( reasonisrhs == (vals[i] > 0.0) )
5080 {
5081 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
5082 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5083 }
5084 else
5085 {
5086 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
5087 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5088 }
5089 }
5090
5091 return SCIP_OKAY;
5092}
5093
5094/** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
5095 * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
5096 * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
5097 */
5098static
5100 SCIP* scip, /**< SCIP data structure */
5101 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5102 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
5103 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5104 int inferpos /**< position of the inferred variable in the vars array, or -1 */
5105 )
5106{
5107 SCIP_CONSDATA* consdata;
5108 SCIP_VAR** vars;
5109 int nvars;
5110 int v;
5111
5112 assert(scip != NULL);
5113 assert(cons != NULL);
5114
5115 consdata = SCIPconsGetData(cons);
5116 assert(consdata != NULL);
5117 vars = consdata->vars;
5118 nvars = consdata->nvars;
5119 assert(vars != NULL || nvars == 0);
5120 assert(-1 <= inferpos && inferpos < nvars);
5121 assert((infervar == NULL) == (inferpos == -1));
5122 assert(inferpos == -1 || vars != NULL);
5123 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5124
5125 /* collect all fixed variables */
5126 for( v = nvars - 1; v >= 0; --v )
5127 {
5128 assert(vars != NULL); /* for flexelint */
5129
5130 /* need to add old bounds before propagation of inferrence variable */
5131 if( vars[v] == infervar )
5132 {
5133 assert(vars[v] != NULL);
5134
5136 {
5137 /* @todo get boundchange index before this last boundchange and correct the index */
5138 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5139 }
5140
5142 {
5143 /* @todo get boundchange index before this last boundchange and correct the index */
5144 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5145 }
5146
5147 continue;
5148 }
5149
5150 /* check for fixed variables */
5151 if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5152 {
5153 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5154 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5155 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5156 }
5157 }
5158
5159 return SCIP_OKAY;
5160}
5161
5162/** add reasoning variables to conflict candidate queue which led to the conflict */
5163static
5165 SCIP* scip, /**< SCIP data structure */
5166 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5167 int nvars, /**< number of variables reasoning the infeasibility */
5168 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5169 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5170 )
5171{
5172 int v;
5173
5174 assert(scip != NULL);
5175
5176 /* collect all variables for which the local bounds differ from their global bounds */
5177 for( v = nvars - 1; v >= 0; --v )
5178 {
5179 assert(vars != NULL);
5180
5181 /* check for local bound changes variables */
5183 {
5184 /* add conflict bound */
5186 }
5187
5189 {
5191 }
5192 }
5193
5194 if( var != NULL )
5195 {
5196 if( bound < SCIPvarGetLbLocal(var) )
5197 {
5199 }
5200
5201 if( bound > SCIPvarGetUbLocal(var) )
5202 {
5204 }
5205 }
5206
5207 return SCIP_OKAY;
5208}
5209
5210/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5211 * propagation rule (see propagateCons()):
5212 * (1) activity residuals of all other variables tighten bounds of single variable
5213 */
5214static
5216 SCIP* scip, /**< SCIP data structure */
5217 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5218 SCIP_VAR* infervar, /**< variable that was deduced */
5219 INFERINFO inferinfo, /**< inference information */
5220 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5221 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5222 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5223 )
5224{
5225 SCIP_CONSDATA* consdata;
5226 SCIP_VAR** vars;
5227#ifndef NDEBUG
5228 SCIP_Real* vals;
5229#endif
5230 int nvars;
5231 int inferpos;
5232
5233 assert(scip != NULL);
5234 assert(cons != NULL);
5235 assert(result != NULL);
5236
5237 consdata = SCIPconsGetData(cons);
5238 assert(consdata != NULL);
5239 vars = consdata->vars;
5240 nvars = consdata->nvars;
5241#ifndef NDEBUG
5242 vals = consdata->vals;
5243 assert(vars != NULL);
5244 assert(vals != NULL);
5245#endif
5246
5247 /* get the position of the inferred variable in the vars array */
5248 inferpos = inferInfoGetPos(inferinfo);
5249 if( inferpos >= nvars || vars[inferpos] != infervar )
5250 {
5251 /* find inference variable in constraint */
5252 /**@todo use a binary search here; the variables can be sorted by variable index */
5253 for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5254 {}
5255 }
5256 assert(inferpos < nvars);
5257 assert(vars[inferpos] == infervar);
5258 assert(!SCIPisZero(scip, vals[inferpos]));
5259
5260 switch( inferInfoGetProprule(inferinfo) )
5261 {
5262 case PROPRULE_1_RHS:
5263 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5264 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5265 * domain in order to not exceed the right hand side of the inequality
5266 */
5267 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5268 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5270 break;
5271
5272 case PROPRULE_1_LHS:
5273 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5274 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5275 * domain in order to not fall below the left hand side of the inequality
5276 */
5277 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5278 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5280 break;
5281
5283 /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5284 * the given inference variable to their bounds in this given ranged row
5285 */
5286
5287 /* check that we really have a ranged row here */
5288 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5289 SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5291 break;
5292
5293 case PROPRULE_INVALID:
5294 default:
5295 SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5296 inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5297 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5298 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5299 SCIPinfoMessage(scip, NULL, ";\n");
5300 return SCIP_INVALIDDATA;
5301 }
5302
5303 return SCIP_OKAY;
5304}
5305
5306/** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5307static
5309 SCIP* scip, /**< SCIP data structure */
5310 SCIP_CONS* cons, /**< conflict detecting constraint */
5311 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5312 )
5313{
5314 /* conflict analysis can only be applied in solving stage and if it is turned on */
5316 return SCIP_OKAY;
5317
5318 /* initialize conflict analysis */
5320
5321 /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5322 SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5323
5324 /* analyze the conflict */
5326
5327 return SCIP_OKAY;
5328}
5329
5330/** check if there is any hope of tightening some bounds */
5331static
5333 SCIP_CONS* cons /**< linear constraint */
5334 )
5335{
5336 SCIP_CONSDATA* consdata;
5337 int infcountmin;
5338 int infcountmax;
5339
5340 consdata = SCIPconsGetData(cons);
5341 assert(consdata != NULL);
5342
5343 infcountmin = consdata->minactivityneginf
5344 + consdata->minactivityposinf
5345 + consdata->minactivityneghuge
5346 + consdata->minactivityposhuge;
5347 infcountmax = consdata->maxactivityneginf
5348 + consdata->maxactivityposinf
5349 + consdata->maxactivityneghuge
5350 + consdata->maxactivityposhuge;
5351
5352 if( infcountmin > 1 && infcountmax > 1 )
5353 return FALSE;
5354
5355 return TRUE;
5356}
5357
5358/** tighten upper bound */
5359static
5361 SCIP* scip, /**< SCIP data structure */
5362 SCIP_CONS* cons, /**< linear constraint */
5363 int pos, /**< variable position */
5364 PROPRULE proprule, /**< propagation rule that deduced the value */
5365 SCIP_Real newub, /**< new upper bound */
5366 SCIP_Real oldub, /**< old upper bound */
5367 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5368 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5369 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5370 )
5371{
5372 SCIP_CONSDATA* consdata;
5373 SCIP_VAR* var;
5374 SCIP_Real lb;
5375 SCIP_Bool infeasible;
5376 SCIP_Bool tightened;
5377
5378 assert(cons != NULL);
5379 assert(!SCIPisInfinity(scip, newub));
5380
5381 consdata = SCIPconsGetData(cons);
5382 assert(consdata != NULL);
5383 var = consdata->vars[pos];
5384 assert(var != NULL);
5385
5386 lb = SCIPvarGetLbLocal(var);
5387 newub = SCIPadjustedVarUb(scip, var, newub);
5388
5389 if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5390 {
5391 SCIP_VARTYPE vartype;
5392
5393 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5394 SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5395 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5396
5397 vartype = SCIPvarGetType(var);
5398
5399 /* tighten upper bound */
5400 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5401
5402 if( infeasible )
5403 {
5404 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5405 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5406
5407 /* analyze conflict */
5409
5410 *cutoff = TRUE;
5411 }
5412 else if( tightened )
5413 {
5415 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5417
5418 (*nchgbds)++;
5419
5420 /* if variable type was changed we might be able to upgrade the constraint */
5421 if( vartype != SCIPvarGetType(var) )
5422 consdata->upgradetried = FALSE;
5423 }
5424 }
5425 return SCIP_OKAY;
5426}
5427
5428/** tighten lower bound */
5429static
5431 SCIP* scip, /**< SCIP data structure */
5432 SCIP_CONS* cons, /**< linear constraint */
5433 int pos, /**< variable position */
5434 PROPRULE proprule, /**< propagation rule that deduced the value */
5435 SCIP_Real newlb, /**< new lower bound */
5436 SCIP_Real oldlb, /**< old lower bound */
5437 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5438 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5439 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5440 )
5441{
5442 SCIP_CONSDATA* consdata;
5443 SCIP_VAR* var;
5444 SCIP_Real ub;
5445 SCIP_Bool infeasible;
5446 SCIP_Bool tightened;
5447
5448 assert(cons != NULL);
5449 assert(!SCIPisInfinity(scip, newlb));
5450
5451 consdata = SCIPconsGetData(cons);
5452 assert(consdata != NULL);
5453 var = consdata->vars[pos];
5454 assert(var != NULL);
5455
5456 ub = SCIPvarGetUbLocal(var);
5457 newlb = SCIPadjustedVarLb(scip, var, newlb);
5458
5459 if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5460 {
5461 SCIP_VARTYPE vartype;
5462
5463 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5464 SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5465 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5466
5467 vartype = SCIPvarGetType(var);
5468
5469 /* tighten lower bound */
5470 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5471
5472 if( infeasible )
5473 {
5474 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5475 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5476
5477 /* analyze conflict */
5479
5480 *cutoff = TRUE;
5481 }
5482 else if( tightened )
5483 {
5485 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5487
5488 (*nchgbds)++;
5489
5490 /* if variable type was changed we might be able to upgrade the constraint */
5491 if( vartype != SCIPvarGetType(var) )
5492 consdata->upgradetried = FALSE;
5493 }
5494 }
5495 return SCIP_OKAY;
5496}
5497
5498/** tightens bounds of a single variable due to activity bounds (easy case) */
5499static
5501 SCIP* scip, /**< SCIP data structure */
5502 SCIP_CONS* cons, /**< linear constraint */
5503 int pos, /**< position of the variable in the vars array */
5504 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5505 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5506 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5507 )
5508{
5509 SCIP_CONSDATA* consdata;
5510 SCIP_VAR* var;
5511 SCIP_Real val;
5512 SCIP_Real lb;
5513 SCIP_Real ub;
5514 SCIP_Real lhs;
5515 SCIP_Real rhs;
5516
5517 assert(scip != NULL);
5518 assert(cons != NULL);
5519 assert(cutoff != NULL);
5520 assert(nchgbds != NULL);
5521
5522 /* we cannot tighten variables' bounds, if the constraint may be not complete */
5523 if( SCIPconsIsModifiable(cons) )
5524 return SCIP_OKAY;
5525
5526 consdata = SCIPconsGetData(cons);
5527 assert(consdata != NULL);
5528 assert(0 <= pos && pos < consdata->nvars);
5529
5530 *cutoff = FALSE;
5531
5532 var = consdata->vars[pos];
5533 assert(var != NULL);
5534
5535 /* we cannot tighten bounds of multi-aggregated variables */
5537 return SCIP_OKAY;
5538
5539 val = consdata->vals[pos];
5540 lhs = consdata->lhs;
5541 rhs = consdata->rhs;
5542 assert(!SCIPisZero(scip, val));
5543 assert(!SCIPisInfinity(scip, lhs));
5544 assert(!SCIPisInfinity(scip, -rhs));
5545
5546 lb = SCIPvarGetLbLocal(var);
5547 ub = SCIPvarGetUbLocal(var);
5548 assert(SCIPisLE(scip, lb, ub));
5549
5550 /* recompute activities if needed */
5551 if( !consdata->validactivities )
5552 consdataCalcActivities(scip, consdata);
5553 assert(consdata->validactivities);
5554 if( !consdata->validminact )
5556 assert(consdata->validminact);
5557
5558 if( val > 0.0 )
5559 {
5560 /* check, if we can tighten the variable's upper bound */
5561 if( !SCIPisInfinity(scip, rhs) )
5562 {
5563 SCIP_Real slack;
5564 SCIP_Real alpha;
5565
5566 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5567 assert(consdata->validminact);
5568
5569 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5570 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5571 {
5572 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5573 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5574
5575 *cutoff = TRUE;
5576 return SCIP_OKAY;
5577 }
5578
5579 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5580
5581 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5582 * it to zero
5583 */
5584 if( !SCIPisPositive(scip, slack) )
5585 slack = 0.0;
5586
5587 alpha = val * (ub - lb);
5589
5590 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5591 {
5592 SCIP_Real newub;
5593
5594 /* compute new upper bound */
5595 newub = lb + (slack / val);
5596
5597 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5598
5599 if( *cutoff )
5600 {
5601 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5602 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5603
5604 return SCIP_OKAY;
5605 }
5606
5607 /* collect the new upper bound which is needed for the lower bound computation */
5608 ub = SCIPvarGetUbLocal(var);
5609 }
5610 }
5611
5612 /* check, if we can tighten the variable's lower bound */
5613 if( !SCIPisInfinity(scip, -lhs) )
5614 {
5615 SCIP_Real slack;
5616 SCIP_Real alpha;
5617
5618 /* make sure the max activity is reliable */
5619 if( !consdata->validmaxact )
5620 {
5622 }
5623 assert(consdata->validmaxact);
5624
5625 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5626 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5627 {
5628 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5629 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5630
5631 *cutoff = TRUE;
5632 return SCIP_OKAY;
5633 }
5634
5635 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5636
5637 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5638 * it to zero
5639 */
5640 if( !SCIPisPositive(scip, slack) )
5641 slack = 0.0;
5642
5643 alpha = val * (ub - lb);
5645
5646 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5647 {
5648 SCIP_Real newlb;
5649
5650 /* compute new lower bound */
5651 newlb = ub - (slack / val);
5652
5653 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5654
5655 if( *cutoff )
5656 {
5657 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5658 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5659
5660 return SCIP_OKAY;
5661 }
5662 }
5663 }
5664 }
5665 else
5666 {
5667 /* check, if we can tighten the variable's lower bound */
5668 if( !SCIPisInfinity(scip, rhs) )
5669 {
5670 SCIP_Real slack;
5671 SCIP_Real alpha;
5672
5673 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5674 assert(consdata->validminact);
5675
5676 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5677 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5678 {
5679 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5680 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5681
5682 *cutoff = TRUE;
5683 return SCIP_OKAY;
5684 }
5685
5686 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5687
5688 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5689 * it to zero
5690 */
5691 if( !SCIPisPositive(scip, slack) )
5692 slack = 0.0;
5693
5694 alpha = val * (lb - ub);
5696
5697 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5698 {
5699 SCIP_Real newlb;
5700
5701 /* compute new lower bound */
5702 newlb = ub + slack / val;
5703
5704 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5705
5706 if( *cutoff )
5707 {
5708 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5709 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5710
5711 return SCIP_OKAY;
5712 }
5713 /* collect the new lower bound which is needed for the upper bound computation */
5714 lb = SCIPvarGetLbLocal(var);
5715 }
5716 }
5717
5718 /* check, if we can tighten the variable's upper bound */
5719 if( !SCIPisInfinity(scip, -lhs) )
5720 {
5721 SCIP_Real slack;
5722 SCIP_Real alpha;
5723
5724 /* make sure the max activity is reliable */
5725 if( !consdata->validmaxact )
5726 {
5728 }
5729 assert(consdata->validmaxact);
5730
5731 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5732 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5733 {
5734 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5735 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5736
5737 *cutoff = TRUE;
5738 return SCIP_OKAY;
5739 }
5740
5741 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5742
5743 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5744 * it to zero
5745 */
5746 if( !SCIPisPositive(scip, slack) )
5747 slack = 0.0;
5748
5749 alpha = val * (lb - ub);
5751
5752 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5753 {
5754 SCIP_Real newub;
5755
5756 /* compute new upper bound */
5757 newub = lb - (slack / val);
5758
5759 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5760
5761 if( *cutoff )
5762 {
5763 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5764 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5765
5766 return SCIP_OKAY;
5767 }
5768 }
5769 }
5770 }
5771
5772 return SCIP_OKAY;
5773}
5774
5775/** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5776static
5778 SCIP* scip, /**< SCIP data structure */
5779 SCIP_CONS* cons, /**< conflict detecting constraint */
5780 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5781 int nvars, /**< number of variables reasoning the infeasibility */
5782 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5783 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5784 )
5785{
5786#ifndef NDEBUG
5787 SCIP_CONSDATA* consdata;
5788
5789 assert(scip != NULL);
5790 assert(cons != NULL);
5791
5792 consdata = SCIPconsGetData(cons);
5793 assert(consdata != NULL);
5794 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5795#endif
5796
5797 /* conflict analysis can only be applied in solving stage and if it is turned on */
5799 return SCIP_OKAY;
5800
5801 /* initialize conflict analysis */
5803
5804 /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5806
5807 /* add reasoning variables to conflict candidate queue which led to the conflict */
5809
5810 /* analyze the conflict */
5812
5813 return SCIP_OKAY;
5814}
5815
5816/** propagate ranged rows
5817 *
5818 * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5819 * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5820 * variables better.
5821 *
5822 * Example:
5823 * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5824 *
5825 * x3 needs to be a multiple of 3, so the instance is infeasible.
5826 *
5827 * Example:
5828 * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5829 *
5830 * The only possible value for x3 is 2, so the variable will be fixed.
5831 *
5832 * @todo add holes if possible
5833 */
5834static
5836 SCIP* scip, /**< SCIP data structure */
5837 SCIP_CONS* cons, /**< linear constraint */
5838 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5839 int* nfixedvars, /**< pointer to count number of fixed variables */
5840 int* nchgbds, /**< pointer to count the number of bound changes */
5841 int* naddconss /**< pointer to count number of added constraints */
5842 )
5843{
5844 SCIP_CONSHDLRDATA* conshdlrdata;
5845 SCIP_CONSHDLR* conshdlr;
5846 SCIP_CONSDATA* consdata;
5847 SCIP_VAR** infcheckvars;
5848 SCIP_Real* infcheckvals;
5849 SCIP_Real minactinfvars;
5850 SCIP_Real maxactinfvars;
5851 SCIP_Real lb;
5852 SCIP_Real ub;
5853 SCIP_Real feastol;
5854 SCIP_Real fixedact;
5855 SCIP_Real lhs;
5856 SCIP_Real rhs;
5857 SCIP_Real absminbincoef;
5858 SCIP_Longint gcd;
5859 SCIP_Longint gcdtmp;
5860 SCIP_Bool minactinfvarsinvalid;
5861 SCIP_Bool maxactinfvarsinvalid;
5862 SCIP_Bool possiblegcd;
5863 SCIP_Bool gcdisone;
5864 SCIP_Bool addartconss;
5865 int ninfcheckvars;
5866 int nunfixedvars;
5867 int nfixedconsvars;
5868 int ncontvars;
5869 int pos;
5870 int v;
5871
5872 assert(scip != NULL);
5873 assert(cons != NULL);
5874 assert(cutoff != NULL);
5875 assert(nfixedvars != NULL);
5876 assert(nchgbds != NULL);
5877 assert(naddconss != NULL);
5878
5879 /* modifiable constraint can be changed so we do not have all necessary information */
5880 if( SCIPconsIsModifiable(cons) )
5881 return SCIP_OKAY;
5882
5883 consdata = SCIPconsGetData(cons);
5884 assert(consdata != NULL);
5885
5886 /* we already did full ranged row propagation */
5887 if( consdata->rangedrowpropagated == 2 )
5888 return SCIP_OKAY;
5889
5890 /* at least three variables are needed */
5891 if( consdata->nvars < 3 )
5892 return SCIP_OKAY;
5893
5894 /* do nothing on normal inequalities */
5895 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5896 return SCIP_OKAY;
5897
5898 /* get constraint handler data */
5899 conshdlr = SCIPconsGetHdlr(cons);
5900 assert(conshdlr != NULL);
5901 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5902 assert(conshdlrdata != NULL);
5903
5904 addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5905
5906 /* we may add artificial constraints */
5907 if( addartconss )
5908 consdata->rangedrowpropagated = 2;
5909 /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5910 * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5911 * artificial constraints
5912 */
5913 else
5914 {
5915 if( consdata->rangedrowpropagated > 0 )
5916 return SCIP_OKAY;
5917
5918 consdata->rangedrowpropagated = 1;
5919 }
5920 fixedact = 0;
5921 nfixedconsvars = 0;
5922 /* calculate fixed activity and number of fixed variables */
5923 for( v = consdata->nvars - 1; v >= 0; --v )
5924 {
5925 /* all zero coefficients should be eliminated */
5926 assert(!SCIPisZero(scip, consdata->vals[v]));
5927
5928 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5929 {
5930 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5931 ++nfixedconsvars;
5932 }
5933 }
5934
5935 /* do not work with huge fixed activities */
5936 if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5937 return SCIP_OKAY;
5938
5939 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5940 assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5941 lhs = consdata->lhs - fixedact;
5942 rhs = consdata->rhs - fixedact;
5943 nunfixedvars = consdata->nvars - nfixedconsvars;
5944
5945 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5946 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5947 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5948
5949 absminbincoef = SCIP_REAL_MAX;
5950 ncontvars = 0;
5951 gcdisone = TRUE;
5952 possiblegcd = TRUE;
5953
5954 /* we now partition all unfixed variables in two groups:
5955 *
5956 * the first one contains all integral variable with integral
5957 * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5958 * given
5959 *
5960 * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5961 * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5962 */
5963
5964 /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5965 * variables
5966 */
5967 ninfcheckvars = 0;
5968 v = -1;
5969 pos = -1;
5970 do
5971 {
5972 ++v;
5973
5974 /* partition the variables, do not change the order of collection, because it might be used later on */
5975 while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5976 !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5977 {
5978 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5979 {
5980 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5981 {
5982 ++ncontvars;
5983 }
5984 else if( SCIPvarIsBinary(consdata->vars[v]) )
5985 {
5986 SCIP_Real absval;
5987
5988 absval = REALABS(consdata->vals[v]);
5989
5990 if( absminbincoef > absval )
5991 absminbincoef = absval;
5992 }
5993
5994 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5995 possiblegcd = FALSE;
5996 infcheckvars[ninfcheckvars] = consdata->vars[v];
5997 infcheckvals[ninfcheckvars] = consdata->vals[v];
5998 ++ninfcheckvars;
5999
6000 if( pos == -1 )
6001 pos = v;
6002 }
6003 ++v;
6004 }
6005 }
6006 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
6007
6008 /* if the first group of variables is empty, we stop */
6009 /* @todo try to propagate/split up a constraint of the form:
6010 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
6011 * 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]
6012 */
6013 if( v == consdata->nvars )
6014 goto TERMINATE;
6015
6016 /* we need at least two non-continuous variables */
6017 if( ncontvars + 2 > nunfixedvars )
6018 goto TERMINATE;
6019
6020 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
6021 assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
6022
6023 feastol = SCIPfeastol(scip);
6024
6025 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
6026 assert(gcd >= 2);
6027
6028 /* go on to partition the variables, do not change the order of collection, because it might be used later on;
6029 * calculate gcd over the first part of variables */
6030 for( ; v < consdata->nvars; ++v )
6031 {
6032 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6033 continue;
6034
6035 if( SCIPvarIsBinary(consdata->vars[v]) )
6036 {
6037 SCIP_Real absval;
6038
6039 absval = REALABS(consdata->vals[v]);
6040
6041 if( absminbincoef > absval )
6042 absminbincoef = absval;
6043 }
6044
6045 if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
6046 SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
6047 {
6048 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
6049 ++ncontvars;
6050
6051 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
6052 possiblegcd = FALSE;
6053 infcheckvars[ninfcheckvars] = consdata->vars[v];
6054 infcheckvals[ninfcheckvars] = consdata->vals[v];
6055
6056 ++ninfcheckvars;
6057
6058 if( pos == -1 )
6059 pos = v;
6060 }
6061 else
6062 {
6063 assert(REALABS(consdata->vals[v]) > 1.5);
6064
6065 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
6066 assert(gcdtmp >= 1);
6067
6068 if( gcdtmp == 1 )
6069 {
6070 infcheckvars[ninfcheckvars] = consdata->vars[v];
6071 infcheckvals[ninfcheckvars] = consdata->vals[v];
6072
6073 ++ninfcheckvars;
6074
6075 if( pos == -1 )
6076 pos = v;
6077 }
6078 else
6079 gcd = gcdtmp;
6080 }
6081 }
6082 assert(gcd >= 2);
6083
6084 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
6085 * normalizeCons() */
6086 if( ninfcheckvars == 0 )
6087 goto TERMINATE;
6088
6089 assert(pos >= 0);
6090
6091 minactinfvarsinvalid = FALSE;
6092 maxactinfvarsinvalid = FALSE;
6093 maxactinfvars = 0.0;
6094 minactinfvars = 0.0;
6095
6096 /* calculate activities over all infcheckvars */
6097 for( v = ninfcheckvars - 1; v >= 0; --v )
6098 {
6099 lb = SCIPvarGetLbLocal(infcheckvars[v]);
6100 ub = SCIPvarGetUbLocal(infcheckvars[v]);
6101
6102 if( SCIPisInfinity(scip, -lb) )
6103 {
6104 if( infcheckvals[v] < 0.0 )
6105 maxactinfvarsinvalid = TRUE;
6106 else
6107 minactinfvarsinvalid = TRUE;
6108 }
6109 else
6110 {
6111 if( infcheckvals[v] < 0.0 )
6112 maxactinfvars += infcheckvals[v] * lb;
6113 else
6114 minactinfvars += infcheckvals[v] * lb;
6115 }
6116
6117 if( SCIPisInfinity(scip, ub) )
6118 {
6119 if( infcheckvals[v] > 0.0 )
6120 maxactinfvarsinvalid = TRUE;
6121 else
6122 minactinfvarsinvalid = TRUE;
6123 }
6124 else
6125 {
6126 if( infcheckvals[v] > 0.0 )
6127 maxactinfvars += infcheckvals[v] * ub;
6128 else
6129 minactinfvars += infcheckvals[v] * ub;
6130 }
6131
6132 /* better abort on to big values */
6133 if( SCIPisHugeValue(scip, -minactinfvars) )
6134 minactinfvarsinvalid = TRUE;
6135 if( SCIPisHugeValue(scip, maxactinfvars) )
6136 maxactinfvarsinvalid = TRUE;
6137
6138 if( minactinfvarsinvalid || maxactinfvarsinvalid )
6139 goto TERMINATE;
6140 }
6141 assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6142
6143 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6144 minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6145
6146 /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6147 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6148 * activities */
6149 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6150 * !!!note!!!
6151 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6152 * are not at their global bound
6153 */
6154
6155 /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6156 * infeasibility */
6157 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6158 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6159 {
6160 SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6162
6163 /* start conflict analysis */
6164 /* @todo improve conflict analysis by adding relaxed bounds */
6165 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6166
6167 *cutoff = TRUE;
6168 }
6169 else if( ncontvars == 0 )
6170 {
6171 SCIP_Longint gcdinfvars = -1;
6172
6173 /* check for gcd over all infcheckvars */
6174 if( possiblegcd )
6175 {
6176 v = ninfcheckvars - 1;
6177 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6178 assert(gcdinfvars >= 2);
6179
6180 for( ; v >= 0 && gcdinfvars >= 2; --v )
6181 {
6182 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6183 }
6184 }
6185 else if( gcdisone )
6186 gcdinfvars = 1;
6187
6188 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6189
6190 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6191 if( gcdinfvars >= 1 )
6192 {
6193 SCIP_Real value;
6194 SCIP_Real value2;
6195 SCIP_Real minvalue = SCIP_INVALID;
6196 SCIP_Real maxvalue = SCIP_INVALID;
6197 int nsols = 0;
6198
6199 value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6200
6201 /* check how many possible solutions exist */
6202 while( SCIPisLE(scip, value, maxactinfvars) )
6203 {
6204 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6205
6206 /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6207 if( !SCIPisGE(scip, value2, lhs) )
6208 {
6209 value2 += gcd;
6210 }
6211
6212 if( SCIPisLE(scip, value2, rhs) )
6213 {
6214 ++nsols;
6215
6216 /* early termination if we found more than two solutions */
6217 if( nsols == 3 )
6218 break;
6219
6220 if( minvalue == SCIP_INVALID ) /*lint !e777*/
6221 minvalue = value;
6222
6223 maxvalue = value;
6224 }
6225 value += gcdinfvars;
6226 }
6227 assert(nsols < 2 || minvalue <= maxvalue);
6228
6229 /* determine last possible solution for better bounding */
6230 if( nsols == 3 )
6231 {
6232#ifndef NDEBUG
6233 SCIP_Real secondsolval = maxvalue;
6234#endif
6235 value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6236
6237 /* check how many possible solutions exist */
6238 while( SCIPisGE(scip, value, minactinfvars) )
6239 {
6240 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6241
6242 /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6243 if( !SCIPisLE(scip, value2, rhs) )
6244 {
6245 value2 -= gcd;
6246 }
6247
6248 if( SCIPisGE(scip, value2, lhs) )
6249 {
6250 maxvalue = value;
6251 assert(maxvalue > minvalue);
6252 break;
6253 }
6254 value -= gcdinfvars;
6255 }
6256 assert(maxvalue > secondsolval);
6257 }
6258
6259 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6260 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6261
6262 /* no possible solution found */
6263 if( nsols == 0 )
6264 {
6265 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6266 gcdinfvars, gcd, lhs, rhs);
6267 SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6269
6270 /* start conflict analysis */
6271 /* @todo improve conflict analysis by adding relaxed bounds */
6272 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6273
6274 *cutoff = TRUE;
6275 }
6276 /* if only one solution exist we can extract a new constraint or fix variables */
6277 else if( nsols == 1 )
6278 {
6279 assert(minvalue == maxvalue); /*lint !e777*/
6280
6281 /* we can fix the only variable in our second set of variables */
6282 if( ninfcheckvars == 1 )
6283 {
6284 SCIP_Bool fixed;
6285
6286 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6287
6288 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6289 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6290 SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6291
6292 /* fix variable to only possible value */
6293 SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6294 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6295
6296 if( *cutoff )
6297 {
6298 /* start conflict analysis */
6299 /* @todo improve conflict analysis by adding relaxed bounds */
6300 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6301 }
6302
6303 if( fixed )
6304 ++(*nfixedvars);
6305 }
6306 else
6307 {
6308 /* check for exactly one unfixed variable which is not part of the infcheckvars */
6309 if( ninfcheckvars == nunfixedvars - 1 )
6310 {
6311 SCIP_Real bound;
6312 SCIP_Bool foundvar = FALSE;
6313 SCIP_Bool fixed;
6314 int w = 0;
6315
6316 assert(ninfcheckvars > 0);
6317
6318 /* find variable which is not an infcheckvar and fix it */
6319 for( v = 0; v < consdata->nvars - 1; ++v )
6320 {
6321 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6322 {
6323 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6324 {
6325#ifndef NDEBUG
6326 int v2 = v + 1;
6327 int w2 = w;
6328
6329 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6330
6331 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6332 {
6333 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6334 continue;
6335
6336 assert(consdata->vars[v2] == infcheckvars[w2]);
6337 ++w2;
6338 }
6339 assert(w2 == ninfcheckvars);
6340#endif
6341 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6342
6343 foundvar = TRUE;
6344
6345 if( consdata->vals[v] < 0 )
6346 {
6347 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6348 }
6349 else
6350 {
6351 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6352 }
6353
6354 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6355 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6356 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6357
6358 /* fix variable to only possible value */
6359 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6361
6362 if( *cutoff )
6363 {
6364 /* start conflict analysis */
6365 /* @todo improve conflict analysis by adding relaxed bounds */
6366 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6367 consdata->vars[v], bound) );
6368 }
6369
6370 if( fixed )
6371 ++(*nfixedvars);
6372
6373 break;
6374 }
6375
6376 ++w;
6377 }
6378 }
6379
6380 /* maybe last variable was the not infcheckvar */
6381 if( !foundvar )
6382 {
6383 assert(v == consdata->nvars - 1);
6384 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6385
6386 if( consdata->vals[v] < 0 )
6387 {
6388 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6389 }
6390 else
6391 {
6392 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6393 }
6394
6395 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6396 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6397 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6398
6399 /* fix variable to only possible value */
6400 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6402
6403 if( *cutoff )
6404 {
6405 /* start conflict analysis */
6406 /* @todo improve conflict analysis by adding relaxed bounds */
6407 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6408 consdata->vars[v], bound) );
6409 }
6410
6411 if( fixed )
6412 ++(*nfixedvars);
6413 }
6414 }
6415 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6416 {
6417 /* aggregation possible if we have two variables, but this will be done later on */
6418 SCIP_CONS* newcons;
6419 char name[SCIP_MAXSTRLEN];
6420
6421 /* create, add, and release new artificial constraint */
6422 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6423 ++conshdlrdata->naddconss;
6424
6425 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6426
6427 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6428 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6429 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6430
6431 SCIPdebugPrintCons(scip, newcons, NULL);
6432
6433 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6434
6435 ++(*naddconss);
6436 }
6437 }
6438 }
6439 /* at least two solutions */
6440 else
6441 {
6442 /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6443
6444 /* only one variable in the second set, so we can bound this variables */
6445 if( ninfcheckvars == 1 )
6446 {
6447 SCIP_Bool tightened;
6448 SCIP_Real newlb;
6449 SCIP_Real newub;
6450
6451 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6452
6453 if( infcheckvals[0] < 0 )
6454 {
6455 newlb = maxvalue/infcheckvals[0];
6456 newub = minvalue/infcheckvals[0];
6457 }
6458 else
6459 {
6460 newlb = minvalue/infcheckvals[0];
6461 newub = maxvalue/infcheckvals[0];
6462 }
6463 assert(newlb < newub);
6464
6465 if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6466 {
6467 /* update lower bound of variable */
6468 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6469 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6470
6471 /* tighten variable lower bound to minimal possible value */
6472 SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6473 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6474
6475 if( *cutoff )
6476 {
6477 /* start conflict analysis */
6478 /* @todo improve conflict analysis by adding relaxed bounds */
6479 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6480 }
6481
6482 if( tightened )
6483 ++(*nchgbds);
6484 }
6485
6486 if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6487 {
6488 /* update upper bound of variable */
6489 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6490 SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6491
6492 /* tighten variable upper bound to maximal possible value */
6493 SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6494 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6495
6496 if( *cutoff )
6497 {
6498 /* start conflict analysis */
6499 /* @todo improve conflict analysis by adding relaxed bounds */
6500 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6501 }
6502
6503 if( tightened )
6504 ++(*nchgbds);
6505 }
6506 }
6507 /* check if we have only one not infcheckvars, if so we can tighten this variable */
6508 else if( ninfcheckvars == nunfixedvars - 1 )
6509 {
6510 SCIP_Bool foundvar = FALSE;
6511 SCIP_Bool tightened;
6512 SCIP_Real newlb;
6513 SCIP_Real newub;
6514 int w = 0;
6515
6516 assert(ninfcheckvars > 0);
6517 assert(minvalue < maxvalue);
6518
6519 /* find variable which is not an infcheckvar and fix it */
6520 for( v = 0; v < consdata->nvars - 1; ++v )
6521 {
6522 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6523 {
6524 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6525 {
6526#ifndef NDEBUG
6527 int v2 = v + 1;
6528 int w2 = w;
6529
6530 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6531
6532 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6533 {
6534 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6535 continue;
6536
6537 assert(consdata->vars[v2] == infcheckvars[w2]);
6538 ++w2;
6539 }
6540 assert(w2 == ninfcheckvars);
6541#endif
6542
6543 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6544 foundvar = TRUE;
6545
6546 if( consdata->vals[v] < 0 )
6547 {
6548 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6549 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6550 }
6551 else
6552 {
6553 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6554 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6555 }
6556 assert(SCIPisLE(scip, newlb, newub));
6557
6558 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6559 {
6560 /* update lower bound of variable */
6561 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6562 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6563
6564 /* tighten variable lower bound to minimal possible value */
6565 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6566 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6567
6568 if( *cutoff )
6569 {
6570 /* start conflict analysis */
6571 /* @todo improve conflict analysis by adding relaxed bounds */
6572 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6573 consdata->vars[v], newlb) );
6574 }
6575
6576 if( tightened )
6577 ++(*nchgbds);
6578 }
6579
6580 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6581 {
6582 /* update upper bound of variable */
6583 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6584 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6585
6586 /* tighten variable upper bound to maximal possible value */
6587 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6588 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6589
6590 if( *cutoff )
6591 {
6592 /* start conflict analysis */
6593 /* @todo improve conflict analysis by adding relaxed bounds */
6594 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6595 consdata->vars[v], newub) );
6596 }
6597
6598 if( tightened )
6599 ++(*nchgbds);
6600 }
6601
6602 break;
6603 }
6604
6605 ++w;
6606 }
6607 }
6608
6609 /* maybe last variable was the not infcheckvar */
6610 if( !foundvar )
6611 {
6612 assert(v == consdata->nvars - 1);
6613 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6614
6615 if( consdata->vals[v] < 0 )
6616 {
6617 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6618 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6619 }
6620 else
6621 {
6622 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6623 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6624 }
6625 assert(SCIPisLE(scip, newlb, newub));
6626
6627 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6628 {
6629 /* update lower bound of variable */
6630 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6631 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6632
6633 /* tighten variable lower bound to minimal possible value */
6634 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6635 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6636
6637 if( *cutoff )
6638 {
6639 /* start conflict analysis */
6640 /* @todo improve conflict analysis by adding relaxed bounds */
6641 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6642 }
6643
6644 if( tightened )
6645 ++(*nchgbds);
6646 }
6647
6648 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6649 {
6650 /* update upper bound of variable */
6651 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6652 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6653
6654 /* tighten variable upper bound to maximal possible value */
6655 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6656 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6657
6658 if( *cutoff )
6659 {
6660 /* start conflict analysis */
6661 /* @todo improve conflict analysis by adding relaxed bounds */
6662 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6663 }
6664
6665 if( tightened )
6666 ++(*nchgbds);
6667 }
6668 }
6669 }
6670 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6671 * region for our infcheckvars, if possible
6672 */
6673 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6674 {
6675 SCIP_CONS* newcons;
6676 char name[SCIP_MAXSTRLEN];
6677 SCIP_Real newlhs;
6678 SCIP_Real newrhs;
6679
6680 assert(maxvalue > minvalue);
6681
6682 if( SCIPisGT(scip, minvalue, minactinfvars) )
6683 newlhs = minvalue;
6684 else
6685 newlhs = -SCIPinfinity(scip);
6686
6687 if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6688 newrhs = maxvalue;
6689 else
6690 newrhs = SCIPinfinity(scip);
6691
6692 if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6693 {
6694 /* create, add, and release new artificial constraint */
6695 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6696 ++conshdlrdata->naddconss;
6697
6698 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6699
6700 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6702 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6703
6704 SCIPdebugPrintCons(scip, newcons, NULL);
6705 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6706
6707 ++(*naddconss);
6708 }
6709 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6710 * should be maxvalue */
6711 }
6712 }
6713 }
6714 }
6715 else if( addartconss && ncontvars < ninfcheckvars )
6716 {
6717 SCIP_Real maxact = 0.0;
6718 SCIP_Real minact = 0.0;
6719 int w = 0;
6720
6721 /* compute activities of non-infcheckvars */
6722 for( v = 0; v < consdata->nvars; ++v )
6723 {
6724 if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6725 {
6726 ++w;
6727 continue;
6728 }
6729
6730 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6731 {
6732 if( SCIPvarIsBinary(consdata->vars[v]) )
6733 {
6734 if( consdata->vals[v] > 0.0 )
6735 maxact += consdata->vals[v];
6736 else
6737 minact += consdata->vals[v];
6738 }
6739 else
6740 {
6741 SCIP_Real tmpval;
6742
6743 assert(SCIPvarIsIntegral(consdata->vars[v]));
6744
6745 if( consdata->vals[v] > 0.0 )
6746 {
6747 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6748
6749 if( SCIPisHugeValue(scip, -tmpval) )
6750 break;
6751
6752 minact += tmpval;
6753
6754 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6755
6756 if( SCIPisHugeValue(scip, tmpval) )
6757 break;
6758
6759 maxact += tmpval;
6760 }
6761 else
6762 {
6763 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6764
6765 if( SCIPisHugeValue(scip, -tmpval) )
6766 break;
6767
6768 minact += tmpval;
6769
6770 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6771
6772 if( SCIPisHugeValue(scip, tmpval) )
6773 break;
6774
6775 maxact += tmpval;
6776 }
6777 }
6778 }
6779 }
6780 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6781 {
6782 SCIP_CONS* newcons;
6783 char name[SCIP_MAXSTRLEN];
6784 SCIP_Real newlhs;
6785 SCIP_Real newrhs;
6786
6787 assert(maxact > minact);
6788 assert(w == ninfcheckvars);
6789
6790 newlhs = lhs - maxact;
6791 newrhs = rhs - minact;
6792 assert(newlhs < newrhs);
6793
6794 /* create, add, and release new artificial constraint */
6795 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6796 ++conshdlrdata->naddconss;
6797
6798 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6799
6800 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6802 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6803
6804 SCIPdebugPrintCons(scip, newcons, NULL);
6805 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6806
6807 ++(*naddconss);
6808 }
6809 }
6810
6811 TERMINATE:
6812 SCIPfreeBufferArray(scip, &infcheckvals);
6813 SCIPfreeBufferArray(scip, &infcheckvars);
6814
6815 return SCIP_OKAY;
6816}
6817
6818/** tightens bounds of a single variable due to activity bounds */
6819static
6821 SCIP* scip, /**< SCIP data structure */
6822 SCIP_CONS* cons, /**< linear constraint */
6823 int pos, /**< position of the variable in the vars array */
6824 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6825 int* nchgbds, /**< pointer to count the total number of tightened bounds */
6826 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6827 )
6828{
6829 SCIP_CONSDATA* consdata;
6830 SCIP_VAR* var;
6831 SCIP_Real val;
6832 SCIP_Real lb;
6833 SCIP_Real ub;
6834 SCIP_Real minresactivity;
6835 SCIP_Real maxresactivity;
6836 SCIP_Real lhs;
6837 SCIP_Real rhs;
6838 SCIP_Bool infeasible;
6839 SCIP_Bool tightened;
6840 SCIP_Bool ismintight;
6841 SCIP_Bool ismaxtight;
6842 SCIP_Bool isminsettoinfinity;
6843 SCIP_Bool ismaxsettoinfinity;
6844
6845 assert(scip != NULL);
6846 assert(cons != NULL);
6847 assert(cutoff != NULL);
6848 assert(nchgbds != NULL);
6849
6850 /* we cannot tighten variables' bounds, if the constraint may be not complete */
6851 if( SCIPconsIsModifiable(cons) )
6852 return SCIP_OKAY;
6853
6854 consdata = SCIPconsGetData(cons);
6855 assert(consdata != NULL);
6856 assert(0 <= pos && pos < consdata->nvars);
6857
6858 *cutoff = FALSE;
6859
6860 var = consdata->vars[pos];
6861
6862 /* we cannot tighten bounds of multi-aggregated variables */
6864 return SCIP_OKAY;
6865
6866 val = consdata->vals[pos];
6867 lhs = consdata->lhs;
6868 rhs = consdata->rhs;
6869 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6870 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
6871 assert(var != NULL);
6872 assert(!SCIPisZero(scip, val));
6873 assert(!SCIPisInfinity(scip, lhs));
6874 assert(!SCIPisInfinity(scip, -rhs));
6875
6876 lb = SCIPvarGetLbLocal(var);
6877 ub = SCIPvarGetUbLocal(var);
6878 assert(SCIPisLE(scip, lb, ub));
6879
6880 if( val > 0.0 )
6881 {
6882 /* check, if we can tighten the variable's bounds */
6883 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight )
6884 {
6885 SCIP_Real newub;
6886
6887 newub = (rhs - minresactivity)/val;
6888
6889 if( !SCIPisInfinity(scip, newub) &&
6890 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6891 {
6892 SCIP_Bool activityunreliable;
6893 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6894
6895 /* check minresactivities for reliability */
6896 if( activityunreliable )
6897 {
6898 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6899 newub = (rhs - minresactivity)/val;
6900 activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6901 (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6902 && (!force || !SCIPisLT(scip, newub, ub)));
6903 }
6904
6905 if( !activityunreliable )
6906 {
6907 /* tighten upper bound */
6908 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6909 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6910 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6911 &infeasible, &tightened) );
6912 if( infeasible )
6913 {
6914 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6915 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6916
6917 /* analyze conflict */
6919
6920 *cutoff = TRUE;
6921 return SCIP_OKAY;
6922 }
6923 if( tightened )
6924 {
6925 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6926 assert(SCIPisFeasLE(scip, ub, newub));
6927 (*nchgbds)++;
6928
6929 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6930 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6931 }
6932 }
6933 }
6934 }
6935
6936 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight )
6937 {
6938 SCIP_Real newlb;
6939
6940 newlb = (lhs - maxresactivity)/val;
6941 if( !SCIPisInfinity(scip, -newlb) &&
6942 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6943 {
6944 /* check maxresactivities for reliability */
6945 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6946 {
6947 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6948 newlb = (lhs - maxresactivity)/val;
6949
6950 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6951 && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6952 && (!force || !SCIPisGT(scip, newlb, lb))) )
6953 return SCIP_OKAY;
6954 }
6955
6956 /* tighten lower bound */
6957 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6958 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6959 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6960 &infeasible, &tightened) );
6961 if( infeasible )
6962 {
6963 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6964 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6965
6966 /* analyze conflict */
6968
6969 *cutoff = TRUE;
6970 return SCIP_OKAY;
6971 }
6972 if( tightened )
6973 {
6974 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6975 assert(SCIPisFeasGE(scip, lb, newlb));
6976 (*nchgbds)++;
6977 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6978 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6979 }
6980 }
6981 }
6982 }
6983 else
6984 {
6985 /* check, if we can tighten the variable's bounds */
6986 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight )
6987 {
6988 SCIP_Real newlb;
6989
6990 newlb = (rhs - minresactivity)/val;
6991 if( !SCIPisInfinity(scip, -newlb) &&
6992 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6993 {
6994 SCIP_Bool activityunreliable;
6995 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6996 /* check minresactivities for reliability */
6997 if( activityunreliable )
6998 {
6999 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
7000 newlb = (rhs - minresactivity)/val;
7001
7002 activityunreliable = SCIPisInfinity(scip, -minresactivity)
7003 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
7004 && (!force || !SCIPisGT(scip, newlb, lb)));
7005 }
7006
7007 if( !activityunreliable )
7008 {
7009 /* tighten lower bound */
7010 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
7011 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
7012 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
7013 &infeasible, &tightened) );
7014 if( infeasible )
7015 {
7016 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7017 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
7018
7019 /* analyze conflict */
7021
7022 *cutoff = TRUE;
7023 return SCIP_OKAY;
7024 }
7025 if( tightened )
7026 {
7027 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7028 assert(SCIPisFeasGE(scip, lb, newlb));
7029 (*nchgbds)++;
7030 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7031 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7032 }
7033 }
7034 }
7035 }
7036
7037 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight )
7038 {
7039 SCIP_Real newub;
7040
7041 newub = (lhs - maxresactivity)/val;
7042 if( !SCIPisInfinity(scip, newub) &&
7043 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
7044 {
7045 /* check maxresactivities for reliability */
7046 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
7047 {
7048 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
7049 newub = (lhs - maxresactivity)/val;
7050
7051 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
7052 && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
7053 && (!force || !SCIPisLT(scip, newub, ub))) )
7054 return SCIP_OKAY;
7055 }
7056
7057 /* tighten upper bound */
7058 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
7059 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
7060 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
7061 &infeasible, &tightened) );
7062 if( infeasible )
7063 {
7064 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7065 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
7066
7067 /* analyze conflict */
7069
7070 *cutoff = TRUE;
7071 return SCIP_OKAY;
7072 }
7073 if( tightened )
7074 {
7075 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7076 assert(SCIPisFeasLE(scip, ub, newub));
7077 (*nchgbds)++;
7078 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7079 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7080 }
7081 }
7082 }
7083 }
7084
7085 return SCIP_OKAY;
7086}
7087
7088#define MAXTIGHTENROUNDS 10
7089
7090/** tightens bounds of variables in constraint due to activity bounds */
7091static
7093 SCIP* scip, /**< SCIP data structure */
7094 SCIP_CONS* cons, /**< linear constraint */
7095 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7096 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7097 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7098 int* nchgbds /**< pointer to count the total number of tightened bounds */
7099 )
7100{
7101 SCIP_CONSDATA* consdata;
7102 unsigned int tightenmode;
7103 int nvars;
7104 int nrounds;
7105 int lastchange;
7106 int oldnchgbds;
7107#ifndef SCIP_DEBUG
7108 int oldnchgbdstotal;
7109#endif
7110 int v;
7111 SCIP_Bool force;
7112 SCIP_Bool easycase;
7113
7114 assert(scip != NULL);
7115 assert(cons != NULL);
7116 assert(nchgbds != NULL);
7117 assert(cutoff != NULL);
7118
7119 *cutoff = FALSE;
7120
7121 /* we cannot tighten variables' bounds, if the constraint may be not complete */
7122 if( SCIPconsIsModifiable(cons) )
7123 return SCIP_OKAY;
7124
7125 /* if a constraint was created after presolve, then it may hold fixed variables
7126 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7127 * thus, ensure here again that variable fixings have been applied
7128 */
7129 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7130 if( *cutoff )
7131 return SCIP_OKAY;
7132
7133 /* check if constraint has any chances of tightening bounds */
7134 if( !canTightenBounds(cons) )
7135 return SCIP_OKAY;
7136
7137 consdata = SCIPconsGetData(cons);
7138 assert(consdata != NULL);
7139
7140 nvars = consdata->nvars;
7141 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7142
7143 /* we are at the root node or during presolving */
7144 if( SCIPgetDepth(scip) < 1 )
7145 tightenmode = 2;
7146 else
7147 tightenmode = 1;
7148
7149 /* stop if we already tightened the constraint and the tightening is not forced */
7150 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7151 return SCIP_OKAY;
7152
7153 /* ensure that the variables are properly sorted */
7154 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7155 {
7156 SCIP_CALL( consdataSort(scip, consdata) );
7157 assert(consdata->coefsorted);
7158 }
7159
7160 /* update maximal activity delta if necessary */
7161 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7163
7164 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7165 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7166 checkMaxActivityDelta(scip, consdata);
7167
7168 /* this may happen if all variables are fixed */
7169 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7170 return SCIP_OKAY;
7171
7172 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7173 {
7174 SCIP_Real slack;
7175 SCIP_Real surplus;
7176 SCIP_Real minactivity;
7177 SCIP_Real maxactivity;
7178 SCIP_Bool ismintight;
7179 SCIP_Bool ismaxtight;
7180 SCIP_Bool isminsettoinfinity;
7181 SCIP_Bool ismaxsettoinfinity;
7182
7183 /* use maximal activity delta to skip propagation (cannot deduce anything) */
7184 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &ismintight, &ismaxtight,
7185 &isminsettoinfinity, &ismaxsettoinfinity);
7186 assert(!SCIPisInfinity(scip, minactivity));
7187 assert(!SCIPisInfinity(scip, -maxactivity));
7188
7189 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7190 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7191
7192 /* check if the constraint will propagate */
7193 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7194 return SCIP_OKAY;
7195 }
7196
7197 /* check if we can use fast implementation for easy and numerically well behaved cases */
7198 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7199
7200 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7201 lastchange = -1;
7202 oldnchgbds = 0;
7203
7204#ifndef SCIP_DEBUG
7205 oldnchgbdstotal = *nchgbds;
7206#endif
7207
7208 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7209 {
7210 /* ensure that the variables are properly sorted
7211 *
7212 * note: it might happen that integer variables become binary during bound tightening at the root node
7213 */
7214 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7215 {
7216 SCIP_CALL( consdataSort(scip, consdata) );
7217 assert(consdata->coefsorted);
7218 }
7219
7220 /* mark the constraint to have the variables' bounds tightened */
7221 consdata->boundstightened = (unsigned int)tightenmode;
7222
7223 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7224 * sorting enables skipping variables
7225 */
7226 v = 0;
7227 while( v < nvars && v != lastchange && !(*cutoff) )
7228 {
7229 oldnchgbds = *nchgbds;
7230
7231 if( easycase )
7232 {
7233 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7234 }
7235 else
7236 {
7237 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7238 }
7239
7240 /* if there was no progress, skip the rest of the binary variables */
7241 if( *nchgbds > oldnchgbds )
7242 {
7243 lastchange = v;
7244 ++v;
7245 }
7246 else if( consdata->coefsorted && v < consdata->nbinvars - 1
7247 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7248 v = consdata->nbinvars;
7249 else
7250 ++v;
7251 }
7252
7253#ifndef SCIP_DEBUG
7254 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7255 *nchgbds - oldnchgbdstotal, nrounds);
7256 oldnchgbdstotal += oldnchgbds;
7257#endif
7258 }
7259
7260#ifndef NDEBUG
7261 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7262 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7263#endif
7264
7265 return SCIP_OKAY;
7266}
7267
7268/** checks linear constraint for feasibility of given solution or current solution */
7269static
7271 SCIP* scip, /**< SCIP data structure */
7272 SCIP_CONS* cons, /**< linear constraint */
7273 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7274 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7275 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7276 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7277 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7278 )
7279{
7280 SCIP_CONSDATA* consdata;
7281 SCIP_Real activity;
7282 SCIP_Real absviol;
7283 SCIP_Real relviol;
7284 SCIP_Real lhsviol;
7285 SCIP_Real rhsviol;
7286
7287 assert(scip != NULL);
7288 assert(cons != NULL);
7289 assert(violated != NULL);
7290
7291 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7293
7294 consdata = SCIPconsGetData(cons);
7295 assert(consdata != NULL);
7296
7297 *violated = FALSE;
7298
7299 if( consdata->row != NULL )
7300 {
7301 if( !checklprows && SCIProwIsInLP(consdata->row) )
7302 return SCIP_OKAY;
7303 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7304 activity = consdataComputePseudoActivity(scip, consdata);
7305 else
7306 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7307 }
7308 else
7309 activity = consdataGetActivity(scip, consdata, sol);
7310
7311 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7312 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7313 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7314 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7315
7316 /* calculate absolute and relative bound violations */
7317 lhsviol = consdata->lhs - activity;
7318 rhsviol = activity - consdata->rhs;
7319
7320 absviol = 0.0;
7321 relviol = 0.0;
7322 if( (lhsviol > 0) && (lhsviol > rhsviol) )
7323 {
7324 absviol = lhsviol;
7325 relviol = SCIPrelDiff(consdata->lhs, activity);
7326 }
7327 else if( rhsviol > 0 )
7328 {
7329 absviol = rhsviol;
7330 relviol = SCIPrelDiff(activity, consdata->rhs);
7331 }
7332
7333 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7334 * return infeasible for safety
7335 */
7336 if( activity == SCIP_INVALID ) /*lint !e777*/
7337 {
7338 assert(sol == NULL);
7339 *violated = TRUE;
7340
7341 /* set violation of invalid pseudo solutions */
7342 absviol = SCIP_INVALID;
7343 relviol = SCIP_INVALID;
7344
7345 /* reset constraint age since we are in enforcement */
7347 }
7348 /* check with relative tolerances (the default) */
7349 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7350 {
7351 /* the "normal" check: one of the two sides is violated */
7352 if( !checkrelmaxabs )
7353 {
7354 *violated = TRUE;
7355
7356 /* only reset constraint age if we are in enforcement */
7357 if( sol == NULL )
7358 {
7360 }
7361 }
7362 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7363 * small compared to the absolute values occurring in the activity
7364 */
7365 else
7366 {
7367 SCIP_Real maxabs;
7368 SCIP_Real coef;
7369 SCIP_Real absval;
7370 SCIP_Real solval;
7371 int v;
7372
7373 maxabs = 1.0;
7374
7375 /* compute maximum absolute value */
7376 for( v = 0; v < consdata->nvars; ++v )
7377 {
7378 if( consdata->vals != NULL )
7379 {
7380 coef = consdata->vals[v];
7381 }
7382 else
7383 coef = 1.0;
7384
7385 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7386 absval = REALABS( coef * solval );
7387 maxabs = MAX( maxabs, absval );
7388 }
7389
7390 /* regard left hand side, first */
7391 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7392 {
7393 /* check whether violation is random noise */
7394 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7395 {
7396 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7397 consdata->lhs - activity, maxabs);
7399
7400 /* only increase constraint age if we are in enforcement */
7401 if( sol == NULL )
7402 {
7403 SCIP_CALL( SCIPincConsAge(scip, cons) );
7404 }
7405 }
7406 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7407 else if( SCIPisZero(scip, consdata->lhs) )
7408 {
7409 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7410 {
7411 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7412 consdata->lhs - activity, maxabs);
7414
7415 /* only increase constraint age if we are in enforcement */
7416 if( sol == NULL )
7417 {
7418 SCIP_CALL( SCIPincConsAge(scip, cons) );
7419 }
7420 }
7421 else
7422 {
7423 *violated = TRUE;
7424
7425 /* only reset constraint age if we are in enforcement */
7426 if( sol == NULL )
7427 {
7429 }
7430 }
7431 }
7432 else
7433 {
7434 *violated = TRUE;
7435
7436 /* only reset constraint age if we are in enforcement */
7437 if( sol == NULL )
7438 {
7440 }
7441 }
7442 }
7443
7444 /* now regard right hand side */
7445 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7446 {
7447 /* check whether violation is random noise */
7448 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7449 {
7450 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7451 activity - consdata->rhs, maxabs);
7453
7454 /* only increase constraint age if we are in enforcement */
7455 if( sol == NULL )
7456 {
7457 SCIP_CALL( SCIPincConsAge(scip, cons) );
7458 }
7459 }
7460 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7461 else if( SCIPisZero(scip, consdata->rhs) )
7462 {
7463 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7464 {
7465 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7466 activity - consdata->rhs, maxabs);
7468
7469 /* only increase constraint age if we are in enforcement */
7470 if( sol == NULL )
7471 {
7472 SCIP_CALL( SCIPincConsAge(scip, cons) );
7473 }
7474 }
7475 else
7476 {
7477 *violated = TRUE;
7478
7479 /* only reset constraint age if we are in enforcement */
7480 if( sol == NULL )
7481 {
7483 }
7484 }
7485 }
7486 else
7487 {
7488 *violated = TRUE;
7489
7490 /* only reset constraint age if we are in enforcement */
7491 if( sol == NULL )
7492 {
7494 }
7495 }
7496 }
7497 }
7498 }
7499 /* check with absolute tolerances */
7500 else if( consdata->checkabsolute &&
7501 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7502 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7503 {
7504 *violated = TRUE;
7505
7506 /* only reset constraint age if we are in enforcement */
7507 if( sol == NULL )
7508 {
7510 }
7511 }
7512 else
7513 {
7514 /* only increase constraint age if we are in enforcement */
7515 if( sol == NULL )
7516 {
7517 SCIP_CALL( SCIPincConsAge(scip, cons) );
7518 }
7519 }
7520
7521 /* update absolute and relative violation of the solution */
7522 if( sol != NULL )
7523 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7524
7525 return SCIP_OKAY;
7526}
7527
7528/** creates an LP row in a linear constraint data */
7529static
7531 SCIP* scip, /**< SCIP data structure */
7532 SCIP_CONS* cons /**< linear constraint */
7533 )
7534{
7535 SCIP_CONSDATA* consdata;
7536
7537 assert(scip != NULL);
7538 assert(cons != NULL);
7539
7540 consdata = SCIPconsGetData(cons);
7541 assert(consdata != NULL);
7542 assert(consdata->row == NULL);
7543
7544 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7546
7547 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7548
7549 return SCIP_OKAY;
7550}
7551
7552/** adds linear constraint as cut to the LP */
7553static
7555 SCIP* scip, /**< SCIP data structure */
7556 SCIP_CONS* cons, /**< linear constraint */
7557 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7558 )
7559{
7560 SCIP_CONSDATA* consdata;
7561
7562 assert(scip != NULL);
7563 assert(cons != NULL);
7564
7565 consdata = SCIPconsGetData(cons);
7566 assert(consdata != NULL);
7567
7568 if( consdata->row == NULL )
7569 {
7570 if( !SCIPconsIsModifiable(cons) )
7571 {
7572 /* 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
7573 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7574 */
7575 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7576 if( *cutoff )
7577 return SCIP_OKAY;
7578 }
7579
7580 /* convert consdata object into LP row */
7581 SCIP_CALL( createRow(scip, cons) );
7582 }
7583 assert(consdata->row != NULL);
7584
7585 if( consdata->nvars == 0 )
7586 {
7587 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7588 }
7589
7590 /* insert LP row as cut */
7591 if( !SCIProwIsInLP(consdata->row) )
7592 {
7593 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7594 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7595 /* if presolving is turned off, the row might be trivial */
7596 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7597 {
7598 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7599 }
7600#ifndef NDEBUG
7601 else
7602 {
7603 int pr;
7604 int cr;
7605 SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7606 SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7607 assert( pr == 0 || cr == 0 );
7608 }
7609#endif
7610 }
7611
7612 return SCIP_OKAY;
7613}
7614
7615/** adds linear constraint as row to the NLP, if not added yet */
7616static
7618 SCIP* scip, /**< SCIP data structure */
7619 SCIP_CONS* cons /**< linear constraint */
7620 )
7621{
7622 SCIP_CONSDATA* consdata;
7623
7625
7626 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7627 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7628 return SCIP_OKAY;
7629
7630 consdata = SCIPconsGetData(cons);
7631 assert(consdata != NULL);
7632
7633 if( consdata->nlrow == NULL )
7634 {
7635 assert(consdata->lhs <= consdata->rhs);
7636
7637 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7638 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7639
7640 assert(consdata->nlrow != NULL);
7641 }
7642
7643 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7644 {
7645 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7646 }
7647
7648 return SCIP_OKAY;
7649}
7650
7651/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7652static
7654 SCIP* scip, /**< SCIP data structure */
7655 SCIP_CONS* cons, /**< linear constraint */
7656 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7657 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7658 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7659 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7660 * the ones with non-zero dual value? */
7661 int* ncuts, /**< pointer to add up the number of found cuts */
7662 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7663 )
7664{
7665 SCIP_CONSDATA* consdata;
7666 SCIP_Bool violated;
7667 int oldncuts;
7668
7669 assert(scip != NULL);
7670 assert(conshdlrdata != NULL);
7671 assert(cons != NULL);
7672 assert(cutoff != NULL);
7673
7674 consdata = SCIPconsGetData(cons);
7675 assert(ncuts != NULL);
7676 assert(consdata != NULL);
7677
7678 oldncuts = *ncuts;
7679 *cutoff = FALSE;
7680
7681 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7682
7683 if( violated )
7684 {
7685 /* insert LP row as cut */
7687 (*ncuts)++;
7688 }
7689 else if( !SCIPconsIsModifiable(cons) && separatecards )
7690 {
7691 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7692 if( !separateall && sol == NULL )
7693 {
7694 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7695 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7696 {
7697 SCIP_Real dualsol;
7698
7699 dualsol = SCIProwGetDualsol(consdata->row);
7700 if( SCIPisFeasNegative(scip, dualsol) )
7701 {
7702 if( !SCIPisInfinity(scip, consdata->rhs) )
7703 {
7704 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7705 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7706 }
7707 }
7708 else if( SCIPisFeasPositive(scip, dualsol) )
7709 {
7710 if( !SCIPisInfinity(scip, -consdata->lhs) )
7711 {
7712 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7713 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7714 }
7715 }
7716 }
7717 }
7718 else
7719 {
7720 if( !SCIPisInfinity(scip, consdata->rhs) )
7721 {
7722 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7723 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7724 }
7725 if( !SCIPisInfinity(scip, -consdata->lhs) )
7726 {
7727 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7728 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7729 }
7730 }
7731 }
7732
7733 if( *ncuts > oldncuts )
7734 {
7736 }
7737
7738 return SCIP_OKAY;
7739}
7740
7741/** propagation method for linear constraints */
7742static
7744 SCIP* scip, /**< SCIP data structure */
7745 SCIP_CONS* cons, /**< linear constraint */
7746 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7747 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7748 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7749 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7750 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7751 int* nchgbds /**< pointer to count the total number of tightened bounds */
7752 )
7753{
7754 SCIP_CONSDATA* consdata;
7755 SCIP_Real minactivity;
7756 SCIP_Real maxactivity;
7757 SCIP_Bool isminacttight;
7758 SCIP_Bool ismaxacttight;
7759 SCIP_Bool isminsettoinfinity;
7760 SCIP_Bool ismaxsettoinfinity;
7761
7762 assert(scip != NULL);
7763 assert(cons != NULL);
7764 assert(cutoff != NULL);
7765 assert(nchgbds != NULL);
7766
7767 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7768
7769 consdata = SCIPconsGetData(cons);
7770 assert(consdata != NULL);
7771
7772 if( consdata->eventdata == NULL )
7773 {
7774 SCIP_CONSHDLR* conshdlr;
7775 SCIP_CONSHDLRDATA* conshdlrdata;
7776
7777 conshdlr = SCIPconsGetHdlr(cons);
7778 assert(conshdlr != NULL);
7779
7780 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7781 assert(conshdlrdata != NULL);
7782
7783 /* catch bound change events of variables */
7784 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7785 assert(consdata->eventdata != NULL);
7786 }
7787
7788 *cutoff = FALSE;
7789
7790 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7791 if( !SCIPconsIsModifiable(cons) )
7792 {
7793 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7795 {
7796 SCIP_CALL( SCIPincConsAge(scip, cons) );
7797 }
7798
7799 /* tighten the variable's bounds */
7800 if( tightenbounds )
7801 {
7802 int oldnchgbds;
7803
7804 oldnchgbds = *nchgbds;
7805
7806 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7807
7808 if( *nchgbds > oldnchgbds )
7809 {
7811 }
7812 }
7813
7814 /* propagate ranged rows */
7815 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7816 {
7817 int nfixedvars;
7818 int naddconss;
7819 SCIPdebug( int oldnchgbds = *nchgbds; )
7820
7821 nfixedvars = 0;
7822 naddconss = 0;
7823
7824 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7825
7826 if( *cutoff )
7827 {
7828 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7829 }
7830 else
7831 {
7832 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7833 }
7834
7835 if( nfixedvars > 0 )
7836 *nchgbds += 2*nfixedvars;
7837 } /*lint !e438*/
7838
7839 /* check constraint for infeasibility and redundancy */
7840 if( !(*cutoff) )
7841 {
7842 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
7843 &isminsettoinfinity, &ismaxsettoinfinity);
7844
7845 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7846 {
7847 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7848 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7849
7850 /* analyze conflict */
7852
7854 *cutoff = TRUE;
7855 }
7856 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7857 {
7858 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7859 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7860
7861 /* analyze conflict */
7863
7865 *cutoff = TRUE;
7866 }
7867 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7868 {
7869 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7870 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7871
7872 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7873 if( consdata->nvars > 0 )
7875 else
7876 SCIP_CALL( SCIPdelCons(scip, cons) );
7877 }
7878 }
7879 }
7880
7881 return SCIP_OKAY;
7882}
7883
7884
7885/*
7886 * Presolving methods
7887 */
7888
7889/** converts all variables with fixed domain into FIXED variables */
7890static
7892 SCIP* scip, /**< SCIP data structure */
7893 SCIP_CONS* cons, /**< linear constraint */
7894 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7895 int* nfixedvars /**< pointer to count the total number of fixed variables */
7896 )
7897{
7898 SCIP_CONSDATA* consdata;
7899 SCIP_VAR* var;
7900 SCIP_VARSTATUS varstatus;
7901 SCIP_Real lb;
7902 SCIP_Real ub;
7903 SCIP_Bool fixed;
7904 SCIP_Bool infeasible;
7905 int v;
7906
7907 assert(scip != NULL);
7908 assert(cons != NULL);
7909 assert(cutoff != NULL);
7910 assert(nfixedvars != NULL);
7911
7912 consdata = SCIPconsGetData(cons);
7913 assert(consdata != NULL);
7914
7915 for( v = 0; v < consdata->nvars; ++v )
7916 {
7917 assert(consdata->vars != NULL);
7918 var = consdata->vars[v];
7919 varstatus = SCIPvarGetStatus(var);
7920
7921 if( varstatus != SCIP_VARSTATUS_FIXED )
7922 {
7923 lb = SCIPvarGetLbGlobal(var);
7924 ub = SCIPvarGetUbGlobal(var);
7925 if( SCIPisEQ(scip, lb, ub) )
7926 {
7927 SCIP_Real fixval;
7928
7929 fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7930 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7931 SCIPvarGetName(var), lb, ub, fixval);
7932 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7933 if( infeasible )
7934 {
7935 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7936 *cutoff = TRUE;
7937 return SCIP_OKAY;
7938 }
7939 if( fixed )
7940 (*nfixedvars)++;
7941 }
7942 }
7943 }
7944
7945 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7946
7947 if( infeasible )
7948 {
7949 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7950 *cutoff = TRUE;
7951 return SCIP_OKAY;
7952 }
7953
7954 assert(consdata->removedfixings);
7955
7956 return SCIP_OKAY;
7957}
7958
7959#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7960
7961/** extracts cliques of the constraint and adds them to SCIP
7962 *
7963 * The following clique extraction mechanism are implemeneted
7964 *
7965 * 1. collect binary variables and sort them in non increasing order, then
7966 *
7967 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7968 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7969 * condition
7970 *
7971 * minactivity + vals[i] + vals[i+1] > rhs
7972 *
7973 * and also add the binary to binary implication also for non-successive variables for which the same argument
7974 * holds
7975 *
7976 * minactivity + vals[i] + vals[j] > rhs
7977 *
7978 * 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
7979 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7980 *
7981 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7982 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7983 * condition
7984 *
7985 * maxactivity + vals[i] + vals[i-1] < lhs
7986 *
7987 * and also add the binary to binary implication also for non-successive variables for which the same argument
7988 * holds
7989 *
7990 * maxactivity + vals[i] + vals[j] < lhs
7991 *
7992 * e.g. you could multiply the above example by -1
7993 *
7994 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7995 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7996 * condition
7997 *
7998 * minactivity - vals[i] - vals[i-1] > rhs
7999 *
8000 * and also add the binary to binary implication also for non-successive variables for which the
8001 * same argument holds
8002 *
8003 * minactivity - vals[i] - vals[j] > rhs
8004 *
8005 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
8006 * implication x1 = 0 => x3 = 1
8007 *
8008 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
8009 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
8010 * condition
8011 *
8012 * maxactivity - vals[i] - vals[i+1] < lhs
8013 *
8014 * and also add the binary to binary implication also for non-successive variables for which the same argument
8015 * holds
8016 *
8017 * maxactivity - vals[i] - vals[j] < lhs
8018 *
8019 * e.g. you could multiply the above example by -1
8020 *
8021 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
8022 * as clique, (this part is done at the end of the method)
8023 *
8024 */
8025static
8027 SCIP* scip, /**< SCIP data structure */
8028 SCIP_CONS* cons, /**< linear constraint */
8029 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
8030 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
8031 int* nfixedvars, /**< pointer to count number of fixed variables */
8032 int* nchgbds, /**< pointer to count the total number of tightened bounds */
8033 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
8034 )
8035{
8036 SCIP_VAR** vars;
8037 SCIP_Real* vals;
8038 SCIP_CONSDATA* consdata;
8039 SCIP_Bool lhsclique;
8040 SCIP_Bool rhsclique;
8041 SCIP_Bool finitelhs;
8042 SCIP_Bool finiterhs;
8043 SCIP_Bool finiteminact;
8044 SCIP_Bool finitemaxact;
8045 SCIP_Bool finitenegminact;
8046 SCIP_Bool finitenegmaxact;
8047 SCIP_Bool finiteposminact;
8048 SCIP_Bool finiteposmaxact;
8049 SCIP_Bool infeasible;
8050 SCIP_Bool stopped;
8051 int cliquenonzerosadded;
8052 int v;
8053 int i;
8054 int nposcoefs;
8055 int nnegcoefs;
8056 int nvars;
8057
8058 assert(scip != NULL);
8059 assert(cons != NULL);
8060 assert(nfixedvars != NULL);
8061 assert(nchgbds != NULL);
8062 assert(cutoff != NULL);
8063 assert(!SCIPconsIsDeleted(cons));
8064
8065 consdata = SCIPconsGetData(cons);
8066 assert(consdata != NULL);
8067
8068 if( consdata->nvars < 2 )
8069 return SCIP_OKAY;
8070
8071 /* add implications if possible
8072 *
8073 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
8074 * maximal absolute contribution and also only if this variable would force all other variables to their bound
8075 * corresponding to the global minimal activity of the constraint
8076 */
8077 if( !consdata->implsadded )
8078 {
8079 /* sort variables by variable type */
8080 SCIP_CALL( consdataSort(scip, consdata) );
8081
8082 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
8083 * up front, might change sorting correspondingly
8084 */
8085 /* fast abort if no binaries seem to exist
8086 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
8087 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
8088 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
8089 * which is the requirement for consdataSort() to actually resort the variables
8090 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
8091 */
8092 if( !SCIPvarIsBinary(consdata->vars[0]) )
8093 return SCIP_OKAY;
8094
8095 nvars = consdata->nvars;
8096 vars = consdata->vars;
8097 vals = consdata->vals;
8098
8099 /* recompute activities if needed */
8100 if( !consdata->validactivities )
8101 consdataCalcActivities(scip, consdata);
8102 assert(consdata->validactivities);
8103
8104 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8105 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8106 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8107 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8108 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8109 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8110 finiteminact = (finitenegminact && finiteposminact);
8111 finitemaxact = (finitenegmaxact && finiteposmaxact);
8112
8113 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8114 {
8115 SCIP_Real maxabscontrib = -1.0;
8116 SCIP_Bool posval = FALSE;
8117 SCIP_Bool allbinary = TRUE;
8118 int oldnchgbds = *nchgbds;
8119 int nbdchgs = 0;
8120 int nimpls = 0;
8121 int position = -1;
8122
8123 /* we need a valid minimal/maximal activity to add cliques */
8124 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8125 {
8127 assert(consdata->validglbminact);
8128 }
8129
8130 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8131 {
8133 assert(consdata->validglbmaxact);
8134 }
8135 assert(consdata->validglbminact || consdata->validglbmaxact);
8136
8137 /* @todo extend this to local/constraint probing */
8138
8139 /* determine maximal contribution to the activity */
8140 for( v = nvars - 1; v >= 0; --v )
8141 {
8142 if( SCIPvarIsBinary(vars[v]) )
8143 {
8144 if( vals[v] > 0 )
8145 {
8146 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8147
8148 if( value > maxabscontrib )
8149 {
8150 maxabscontrib = value;
8151 position = v;
8152 posval = TRUE;
8153 }
8154 }
8155 else
8156 {
8157 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8158
8159 value = REALABS(value);
8160
8161 if( value > maxabscontrib )
8162 {
8163 maxabscontrib = value;
8164 position = v;
8165 posval = FALSE;
8166 }
8167 }
8168 }
8169 else
8170 allbinary = FALSE;
8171 }
8172 assert(0 <= position && position < nvars);
8173
8174 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8175 {
8176 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8177 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8178 * implications
8179 */
8180 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8181 {
8182 for( v = nvars - 1; v >= 0; --v )
8183 {
8184 /* binary to binary implications will be collected when extrating cliques */
8185 if( !SCIPvarIsBinary(vars[v]) )
8186 {
8187 if( v != position )
8188 {
8189 if( vals[v] > 0 )
8190 {
8191 /* add implications */
8192 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8193 ++nimpls;
8194 *nchgbds += nbdchgs;
8195 }
8196 else
8197 {
8198 /* add implications */
8199 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8200 ++nimpls;
8201 *nchgbds += nbdchgs;
8202 }
8203
8204 if( infeasible )
8205 {
8206 *cutoff = TRUE;
8207 break;
8208 }
8209 }
8210 }
8211 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8212 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8213 break;
8214 }
8215 }
8216
8217 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8218 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8219 * implications
8220 */
8221 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8222 {
8223 for( v = nvars - 1; v >= 0; --v )
8224 {
8225 /* binary to binary implications will be collected when extrating cliques */
8226 if( !SCIPvarIsBinary(vars[v]) )
8227 {
8228 if( v != position )
8229 {
8230 if( vals[v] > 0 )
8231 {
8232 /* add implications */
8233 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8234 ++nimpls;
8235 *nchgbds += nbdchgs;
8236 }
8237 else
8238 {
8239 /* add implications */
8240 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8241 ++nimpls;
8242 *nchgbds += nbdchgs;
8243 }
8244
8245 if( infeasible )
8246 {
8247 *cutoff = TRUE;
8248 break;
8249 }
8250 }
8251 }
8252 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8253 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8254 break;
8255 }
8256 }
8257
8258 /* did we find some implications */
8259 if( nimpls > 0 )
8260 {
8261 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8262
8263 if( *cutoff )
8264 return SCIP_OKAY;
8265
8266 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8267 if( *nchgbds - oldnchgbds > 0 )
8268 {
8269 /* check for fixed variables */
8270 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8271 if( *cutoff )
8272 return SCIP_OKAY;
8273
8274 /* tighten variable's bounds */
8275 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8276 if( *cutoff )
8277 return SCIP_OKAY;
8278
8279 /* check for fixed variables */
8280 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8281 if( *cutoff )
8282 return SCIP_OKAY;
8283 }
8284 }
8285 }
8286 }
8287
8288 consdata->implsadded = TRUE;
8289 }
8290
8291 /* check if we already added the cliques of this constraint */
8292 if( consdata->cliquesadded )
8293 return SCIP_OKAY;
8294
8295 consdata->cliquesadded = TRUE;
8296 cliquenonzerosadded = 0;
8297 stopped = FALSE;
8298
8299 /* sort variables by variable type */
8300 SCIP_CALL( consdataSort(scip, consdata) );
8301
8302 nvars = consdata->nvars;
8303 vars = consdata->vars;
8304 vals = consdata->vals;
8305
8306 /**@todo extract more cliques, implications and variable bounds from linear constraints */
8307
8308 /* recompute activities if needed */
8309 if( !consdata->validactivities )
8310 consdataCalcActivities(scip, consdata);
8311 assert(consdata->validactivities);
8312
8313 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8314 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8315 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8316 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8317 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8318 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8319 finiteminact = (finitenegminact && finiteposminact);
8320 finitemaxact = (finitenegmaxact && finiteposmaxact);
8321
8322 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8323 * information
8324 */
8325 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8326 {
8327 SCIP_VAR** binvars;
8328 SCIP_Real* binvarvals;
8329 int nposbinvars = 0;
8330 int nnegbinvars = 0;
8331 int allonebinary = 0;
8332
8334 SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8335
8336 /* collect binary variables */
8337 for( i = 0; i < nvars; ++i )
8338 {
8339 if( SCIPvarIsBinary(vars[i]) )
8340 {
8341 assert(!SCIPisZero(scip, vals[i]));
8342
8343 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8344 ++allonebinary;
8345
8346 binvars[nposbinvars + nnegbinvars] = vars[i];
8347 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8348
8349 if( SCIPisPositive(scip, vals[i]) )
8350 ++nposbinvars;
8351 else
8352 ++nnegbinvars;
8353
8354 assert(nposbinvars + nnegbinvars <= nvars);
8355 }
8356 /* stop searching for binary variables, because the constraint data is sorted */
8358 break;
8359 }
8360 assert(nposbinvars + nnegbinvars <= nvars);
8361
8362 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8363 * cliques
8364 */
8365 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8366 {
8367 SCIP_Real threshold;
8368 int oldnchgbds = *nchgbds;
8369 int nbdchgs;
8370 int jstart;
8371 int j;
8372
8373 /* we need a valid minimal/maximal activity to add cliques */
8374 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8375 {
8377 assert(consdata->validglbminact);
8378 }
8379
8380 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8381 {
8383 assert(consdata->validglbmaxact);
8384 }
8385 assert(consdata->validglbminact || consdata->validglbmaxact);
8386
8387 /* sort coefficients non-increasing to be faster in the clique search */
8388 SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8389
8390 /* case a) */
8391 if( finiterhs && finitenegminact && nposbinvars >= 2 )
8392 {
8393 /* compute value that needs to be exceeded */
8394 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8395
8396 j = 1;
8397#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8398 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8399 assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8400#endif
8401 /* check if at least two variables are in a clique */
8402 if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8403 {
8404 ++j;
8405 /* check for extending the clique */
8406 while( j < nposbinvars )
8407 {
8408 if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8409 break;
8410 ++j;
8411 }
8412 assert(j >= 2);
8413
8414 /* add clique with at least two variables */
8415 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8416
8417 if( infeasible )
8418 *cutoff = TRUE;
8419
8420 *nchgbds += nbdchgs;
8421
8422 cliquenonzerosadded += j;
8423 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8424 stopped = TRUE;
8425
8426 /* exchange the last variable in the clique if possible and add all new ones */
8427 if( !stopped && !(*cutoff) && j < nposbinvars )
8428 {
8429 SCIP_VAR** clqvars;
8430 int lastfit = j - 2;
8431 assert(lastfit >= 0);
8432
8433 /* copy all 'main'-clique variables */
8434 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8435
8436 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8437 while( lastfit >= 0 && j < nposbinvars )
8438 {
8439 /* check if two variables are in a clique */
8440 if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8441 {
8442 clqvars[lastfit + 1] = binvars[j];
8443
8444 /* add clique with at least two variables */
8445 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8446
8447 if( infeasible )
8448 {
8449 *cutoff = TRUE;
8450 break;
8451 }
8452
8453 *nchgbds += nbdchgs;
8454
8455 cliquenonzerosadded += (lastfit + 2);
8456 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8457 {
8458 stopped = TRUE;
8459 break;
8460 }
8461
8462 ++j;
8463 }
8464 else
8465 --lastfit;
8466 }
8467
8468 SCIPfreeBufferArray(scip, &clqvars);
8469 }
8470 }
8471 }
8472
8473 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8474 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8475 {
8476 /* check for fixed variables */
8477 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8478
8479 if( !*cutoff )
8480 {
8481 /* tighten variable's bounds */
8482 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8483
8484 if( !*cutoff )
8485 {
8486 /* check for fixed variables */
8487 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8488
8489 if( !*cutoff )
8490 {
8491 /* sort variables by variable type */
8492 SCIP_CALL( consdataSort(scip, consdata) );
8493
8494 /* recompute activities if needed */
8495 if( !consdata->validactivities )
8496 consdataCalcActivities(scip, consdata);
8497 assert(consdata->validactivities);
8498
8499 nvars = consdata->nvars;
8500 vars = consdata->vars;
8501 vals = consdata->vals;
8502 nposbinvars = 0;
8503 nnegbinvars = 0;
8504 allonebinary = 0;
8505
8506 /* update binary variables */
8507 for( i = 0; i < nvars; ++i )
8508 {
8509 if( SCIPvarIsBinary(vars[i]) )
8510 {
8511 assert(!SCIPisZero(scip, vals[i]));
8512
8513 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8514 ++allonebinary;
8515
8516 binvars[nposbinvars + nnegbinvars] = vars[i];
8517 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8518
8519 if( SCIPisPositive(scip, vals[i]) )
8520 ++nposbinvars;
8521 else
8522 ++nnegbinvars;
8523
8524 assert(nposbinvars + nnegbinvars <= nvars);
8525 }
8526 /* stop searching for binary variables, because the constraint data is sorted */
8528 break;
8529 }
8530 assert(nposbinvars + nnegbinvars <= nvars);
8531 }
8532 }
8533 }
8534
8535 oldnchgbds = *nchgbds;
8536 }
8537
8538 /* case b) */
8539 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8540 {
8541 /* compute value that needs to be deceeded */
8542 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8543
8544 i = nposbinvars + nnegbinvars - 1;
8545 j = i - 1;
8546#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8547 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8548 assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8549#endif
8550 /* check if two variables are in a clique */
8551 if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8552 {
8553 --j;
8554 /* check for extending the clique */
8555 while( j >= nposbinvars )
8556 {
8557 if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8558 break;
8559 --j;
8560 }
8561 jstart = j;
8562
8563 assert(i - j >= 2);
8564 /* add clique with at least two variables */
8565 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8566
8567 if( infeasible )
8568 *cutoff = TRUE;
8569
8570 *nchgbds += nbdchgs;
8571
8572 cliquenonzerosadded += (i - j);
8573 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8574 stopped = TRUE;
8575
8576 /* exchange the last variable in the clique if possible and add all new ones */
8577 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8578 {
8579 SCIP_VAR** clqvars;
8580 int lastfit = jstart + 1;
8581 assert(lastfit < i);
8582
8583 /* copy all 'main'-clique variables */
8584 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8585 ++lastfit;
8586
8587 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8588 while( lastfit <= i && j >= nposbinvars )
8589 {
8590 /* check if two variables are in a clique */
8591 if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8592 {
8593 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8594 clqvars[lastfit - jstart - 2] = binvars[j];
8595
8596 assert(i - lastfit + 2 >= 2);
8597 /* add clique with at least two variables */
8598 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8599
8600 if( infeasible )
8601 {
8602 *cutoff = TRUE;
8603 break;
8604 }
8605
8606 *nchgbds += nbdchgs;
8607
8608 cliquenonzerosadded += (i - lastfit + 2);
8609 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8610 {
8611 stopped = TRUE;
8612 break;
8613 }
8614
8615 --j;
8616 }
8617 else
8618 ++lastfit;
8619 }
8620
8621 SCIPfreeBufferArray(scip, &clqvars);
8622 }
8623 }
8624 }
8625
8626 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8627 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8628 {
8629 /* check for fixed variables */
8630 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8631
8632 if( !*cutoff )
8633 {
8634 /* tighten variable's bounds */
8635 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8636
8637 if( !*cutoff )
8638 {
8639 /* check for fixed variables */
8640 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8641
8642 if( !*cutoff )
8643 {
8644 /* sort variables by variable type */
8645 SCIP_CALL( consdataSort(scip, consdata) );
8646
8647 /* recompute activities if needed */
8648 if( !consdata->validactivities )
8649 consdataCalcActivities(scip, consdata);
8650 assert(consdata->validactivities);
8651
8652 nvars = consdata->nvars;
8653 vars = consdata->vars;
8654 vals = consdata->vals;
8655 nposbinvars = 0;
8656 nnegbinvars = 0;
8657 allonebinary = 0;
8658
8659 /* update binary variables */
8660 for( i = 0; i < nvars; ++i )
8661 {
8662 if( SCIPvarIsBinary(vars[i]) )
8663 {
8664 assert(!SCIPisZero(scip, vals[i]));
8665
8666 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8667 ++allonebinary;
8668
8669 binvars[nposbinvars + nnegbinvars] = vars[i];
8670 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8671
8672 if( SCIPisPositive(scip, vals[i]) )
8673 ++nposbinvars;
8674 else
8675 ++nnegbinvars;
8676
8677 assert(nposbinvars + nnegbinvars <= nvars);
8678 }
8679 /* stop searching for binary variables, because the constraint data is sorted */
8681 break;
8682 }
8683 assert(nposbinvars + nnegbinvars <= nvars);
8684 }
8685 }
8686 }
8687
8688 oldnchgbds = *nchgbds;
8689 }
8690
8691 /* case c) */
8692 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8693 {
8694 SCIP_Bool* values;
8695
8696 /* initialize clique values array for adding a negated clique */
8697 SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8698 BMSclearMemoryArray(values, nnegbinvars);
8699
8700 /* compute value that needs to be exceeded */
8701 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8702
8703 i = nposbinvars + nnegbinvars - 1;
8704 j = i - 1;
8705
8706#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8707 /* check if the variable should not have already been fixed to one */
8708 assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8709#endif
8710
8711 if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8712 {
8713 --j;
8714 /* check for extending the clique */
8715 while( j >= nposbinvars )
8716 {
8717 if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8718 break;
8719 --j;
8720 }
8721 jstart = j;
8722
8723 assert(i - j >= 2);
8724 /* add negated clique with at least two variables */
8725 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8726
8727 if( infeasible )
8728 *cutoff = TRUE;
8729
8730 *nchgbds += nbdchgs;
8731
8732 cliquenonzerosadded += (i - j);
8733 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8734 stopped = TRUE;
8735
8736 /* exchange the last variable in the clique if possible and add all new ones */
8737 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8738 {
8739 SCIP_VAR** clqvars;
8740 int lastfit = j + 1;
8741 assert(lastfit < i);
8742
8743 /* copy all 'main'-clique variables */
8744 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8745 ++lastfit;
8746
8747 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8748 while( lastfit <= i && j >= nposbinvars )
8749 {
8750 /* check if two variables are in a negated clique */
8751 if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8752 {
8753 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8754 clqvars[lastfit - jstart - 2] = binvars[j];
8755
8756 assert(i - lastfit + 2 >= 2);
8757 /* add clique with at least two variables */
8758 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8759
8760 if( infeasible )
8761 {
8762 *cutoff = TRUE;
8763 break;
8764 }
8765
8766 *nchgbds += nbdchgs;
8767
8768 cliquenonzerosadded += (i - lastfit + 2);
8769 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8770 {
8771 stopped = TRUE;
8772 break;
8773 }
8774
8775 --j;
8776 }
8777 else
8778 ++lastfit;
8779 }
8780
8781 SCIPfreeBufferArray(scip, &clqvars);
8782 }
8783 }
8784
8785 SCIPfreeBufferArray(scip, &values);
8786 }
8787
8788 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8789 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8790 {
8791 /* check for fixed variables */
8792 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8793
8794 if( !*cutoff )
8795 {
8796 /* tighten variable's bounds */
8797 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8798
8799 if( !*cutoff )
8800 {
8801 /* check for fixed variables */
8802 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8803
8804 if( !*cutoff )
8805 {
8806 /* sort variables by variable type */
8807 SCIP_CALL( consdataSort(scip, consdata) );
8808
8809 /* recompute activities if needed */
8810 if( !consdata->validactivities )
8811 consdataCalcActivities(scip, consdata);
8812 assert(consdata->validactivities);
8813
8814 nvars = consdata->nvars;
8815 vars = consdata->vars;
8816 vals = consdata->vals;
8817 nposbinvars = 0;
8818 nnegbinvars = 0;
8819 allonebinary = 0;
8820
8821 /* update binary variables */
8822 for( i = 0; i < nvars; ++i )
8823 {
8824 if( SCIPvarIsBinary(vars[i]) )
8825 {
8826 assert(!SCIPisZero(scip, vals[i]));
8827
8828 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8829 ++allonebinary;
8830
8831 binvars[nposbinvars + nnegbinvars] = vars[i];
8832 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8833
8834 if( SCIPisPositive(scip, vals[i]) )
8835 ++nposbinvars;
8836 else
8837 ++nnegbinvars;
8838
8839 assert(nposbinvars + nnegbinvars <= nvars);
8840 }
8841 /* stop searching for binary variables, because the constraint data is sorted */
8843 break;
8844 }
8845 assert(nposbinvars + nnegbinvars <= nvars);
8846 }
8847 }
8848 }
8849 }
8850
8851 /* case d) */
8852 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8853 {
8854 SCIP_Bool* values;
8855
8856 /* initialize clique values array for adding a negated clique */
8857 SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8858 BMSclearMemoryArray(values, nposbinvars);
8859
8860 /* compute value that needs to be exceeded */
8861 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8862
8863 j = 1;
8864
8865#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8866 /* check if the variable should not have already been fixed to one */
8867 assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8868#endif
8869
8870 if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8871 {
8872 ++j;
8873 /* check for extending the clique */
8874 while( j < nposbinvars )
8875 {
8876 if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8877 break;
8878 ++j;
8879 }
8880 assert(j >= 2);
8881
8882 /* add negated clique with at least two variables */
8883 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8884
8885 if( infeasible )
8886 *cutoff = TRUE;
8887
8888 *nchgbds += nbdchgs;
8889
8890 cliquenonzerosadded += j;
8891 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8892 stopped = TRUE;
8893
8894 /* exchange the last variable in the clique if possible and add all new ones */
8895 if( !stopped && !(*cutoff) && j < nposbinvars )
8896 {
8897 SCIP_VAR** clqvars;
8898 int lastfit = j - 2;
8899 assert(lastfit >= 0);
8900
8901 /* copy all 'main'-clique variables */
8902 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8903
8904 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8905 while( lastfit >= 0 && j < nposbinvars )
8906 {
8907 /* check if two variables are in a negated clique */
8908 if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8909 {
8910 clqvars[lastfit + 1] = binvars[j];
8911
8912 /* add clique with at least two variables */
8913 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8914
8915 if( infeasible )
8916 {
8917 *cutoff = TRUE;
8918 break;
8919 }
8920
8921 *nchgbds += nbdchgs;
8922
8923 cliquenonzerosadded += lastfit + 2;
8924 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8925 break;
8926
8927 ++j;
8928 }
8929 else
8930 --lastfit;
8931 }
8932
8933 SCIPfreeBufferArray(scip, &clqvars);
8934 }
8935 }
8936
8937 SCIPfreeBufferArray(scip, &values);
8938 }
8939 }
8940
8941 SCIPfreeBufferArray(scip, &binvarvals);
8942 SCIPfreeBufferArray(scip, &binvars);
8943
8944 if( *cutoff )
8945 return SCIP_OKAY;
8946 }
8947
8948 /* 2. we only check if the constraint is a set packing / partitioning constraint */
8949
8950 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8951 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8952 */
8953 nposcoefs = 0;
8954 nnegcoefs = 0;
8955 for( i = 0; i < nvars; ++i )
8956 {
8957 if( !SCIPvarIsBinary(vars[i]) )
8958 return SCIP_OKAY;
8959 else if( SCIPisEQ(scip, vals[i], +1.0) )
8960 nposcoefs++;
8961 else if( SCIPisEQ(scip, vals[i], -1.0) )
8962 nnegcoefs++;
8963 else
8964 return SCIP_OKAY;
8965 }
8966
8967 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8968 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8969
8970 if( lhsclique || rhsclique )
8971 {
8972 SCIP_Bool* values;
8973 int nbdchgs;
8974
8975 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8976 SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8978
8979 for( i = 0; i < nvars; ++i )
8980 values[i] = (rhsclique == (vals[i] > 0.0));
8981
8982 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8983
8984 if( infeasible )
8985 *cutoff = TRUE;
8986
8987 *nchgbds += nbdchgs;
8988 SCIPfreeBufferArray(scip, &values);
8989 }
8990
8991 return SCIP_OKAY;
8992}
8993
8994/** tightens left and right hand side of constraint due to integrality */
8995static
8997 SCIP* scip, /**< SCIP data structure */
8998 SCIP_CONS* cons, /**< linear constraint */
8999 int* nchgsides, /**< pointer to count number of side changes */
9000 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
9001 )
9002{
9003 SCIP_CONSDATA* consdata;
9004 SCIP_Real newlhs;
9005 SCIP_Real newrhs;
9006 SCIP_Bool chglhs;
9007 SCIP_Bool chgrhs;
9008 SCIP_Bool integral;
9009 int i;
9010
9011 assert(scip != NULL);
9012 assert(cons != NULL);
9013 assert(nchgsides != NULL);
9014 assert(infeasible != NULL);
9015
9016 consdata = SCIPconsGetData(cons);
9017 assert(consdata != NULL);
9018
9019 *infeasible = FALSE;
9020
9021 chglhs = FALSE;
9022 chgrhs = FALSE;
9023 newlhs = -SCIPinfinity(scip);
9024 newrhs = SCIPinfinity(scip);
9025
9026 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
9027 {
9028 integral = TRUE;
9029 for( i = 0; i < consdata->nvars && integral; ++i )
9030 {
9031 integral = SCIPisIntegral(scip, consdata->vals[i])
9032 && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
9033 }
9034 if( integral )
9035 {
9036 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
9037 {
9038 newlhs = SCIPfeasCeil(scip, consdata->lhs);
9039 chglhs = TRUE;
9040 }
9041 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
9042 {
9043 newrhs = SCIPfeasFloor(scip, consdata->rhs);
9044 chgrhs = TRUE;
9045 }
9046
9047 /* check whether rounding would lead to an unsatisfiable constraint */
9048 if( SCIPisGT(scip, newlhs, newrhs) )
9049 {
9050 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
9051 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
9052
9053 *infeasible = TRUE;
9054 return SCIP_OKAY;
9055 }
9056
9057 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
9058 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9059
9060 if( chglhs )
9061 {
9062 assert(!SCIPisInfinity(scip, -newlhs));
9063
9064 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9065 if( !consdata->upgraded )
9066 (*nchgsides)++;
9067 }
9068 if( chgrhs )
9069 {
9070 assert(!SCIPisInfinity(scip, newrhs));
9071
9072 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9073 if( !consdata->upgraded )
9074 (*nchgsides)++;
9075 }
9076 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
9077 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9078 }
9079 }
9080
9081 return SCIP_OKAY;
9082}
9083
9084/** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
9085 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
9086 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
9087 * (i) ai >= 0:
9088 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
9089 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
9090 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9091 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9092 * - change coefficients:
9093 * ai' := max(lhs - minact, maxact - rhs)
9094 * lhs' := lhs - (ai - ai')*li
9095 * rhs' := rhs - (ai - ai')*ui
9096 * (ii) ai < 0:
9097 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9098 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9099 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9100 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9101 * - change coefficients:
9102 * ai' := min(rhs - maxact, minact - lhs)
9103 * lhs' := lhs - (ai - ai')*ui
9104 * rhs' := rhs - (ai - ai')*li
9105 *
9106 * We further try to remove redundant variable from the constraint;
9107 * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
9108 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9109 * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
9110 * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
9111 * E.g., for binary variables and an inequality x_1 +x_2 +10y_1 +10y_2 >= 5, setting either of the y_i to one
9112 * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
9113 *
9114 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9115 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9116 */
9117static
9119 SCIP* scip, /**< SCIP data structure */
9120 SCIP_CONS* cons, /**< linear constraint */
9121 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9122 int* nchgsides /**< pointer to count number of side changes */
9123 )
9124{
9125 SCIP_CONSDATA* consdata;
9126 SCIP_VAR* var;
9127 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9128 * activity, ignoring the coefficients contributing with infinite value */
9129 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9130 * activity, ignoring the coefficients contributing with infinite value */
9131 SCIP_Bool isminacttight; /* are all contributions to the minactivity non-huge or non-contradicting? */
9132 SCIP_Bool ismaxacttight; /* are all contributions to the maxactivity non-huge or non-contradicting? */
9133 SCIP_Bool isminsettoinfinity;
9134 SCIP_Bool ismaxsettoinfinity;
9135 SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
9136 SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
9137 SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
9138 SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
9139 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9140 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9141 SCIP_Real val;
9142 SCIP_Real newval;
9143 SCIP_Real newlhs;
9144 SCIP_Real newrhs;
9145 SCIP_Real lb;
9146 SCIP_Real ub;
9147 int i;
9148
9149 assert(scip != NULL);
9150 assert(cons != NULL);
9151 assert(nchgcoefs != NULL);
9152 assert(nchgsides != NULL);
9153
9154 consdata = SCIPconsGetData(cons);
9155 assert(consdata != NULL);
9156
9157 /* @todo Is this still needed with automatic recomputation of activities? */
9158 /* if the maximal coefficient is too large, recompute the activities */
9159 if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9160 || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9161 {
9164 }
9165
9166 /* get the minimal and maximal activity of the constraint */
9167 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9168 &isminsettoinfinity, &ismaxsettoinfinity);
9169
9170 minleftactivity = 0.0;
9171 maxleftactivity = 0.0;
9172
9173 /* try to tighten each coefficient */
9174 i = 0;
9175 while( i < consdata->nvars )
9176 {
9177 var = consdata->vars[i];
9178
9179 /* get coefficient and variable's bounds */
9180 lb = SCIPvarGetLbLocal(var);
9181 ub = SCIPvarGetUbLocal(var);
9182 val = consdata->vals[i];
9183 assert(!SCIPisZero(scip, val));
9184
9185 /* check sign of coefficient */
9186 if( val >= 0.0 )
9187 {
9188 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9190 SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
9191 {
9192 /* change coefficients:
9193 * ai' := max(lhs - minact, maxact - rhs)
9194 * lhs' := lhs - (ai - ai')*li
9195 * rhs' := rhs - (ai - ai')*ui
9196 */
9197
9198 lval = consdata->lhs - minactivity;
9199 rval = maxactivity - consdata->rhs;
9200
9201 /* Try to avoid cancellation, if there are only two variables */
9202 if( consdata->nvars == 2 )
9203 {
9204 SCIP_Real otherval;
9205 otherval = consdata->vals[1-i];
9206
9207 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9208 {
9209 lval = consdata->lhs - val*lb;
9210 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9211 }
9212
9213 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9214 {
9215 rval = val*ub - consdata->rhs;
9216 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9217 }
9218 }
9219
9220 newval = MAX(lval, rval);
9221 assert(SCIPisSumRelLE(scip, newval, val));
9222
9223 /* Try to avoid cancellation in computation of lhs/rhs */
9224 newlhs = consdata->lhs - val * lb;
9225 newlhs += newval * lb;
9226 newrhs = consdata->rhs - val * ub;
9227 newrhs += newval * ub;
9228
9229 if( !SCIPisSumRelEQ(scip, newval, val) )
9230 {
9231 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9232 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9233 minactivity, maxactivity, consdata->lhs, consdata->rhs);
9234
9235 /* update the coefficient and the activity bounds */
9236 if( SCIPisZero(scip, newval) )
9237 {
9238 SCIP_CALL( delCoefPos(scip, cons, i) );
9239 i--;
9240 }
9241 else
9242 {
9243 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9244 }
9245 (*nchgcoefs)++;
9246
9247 /* get the new minimal and maximal activity of the constraint */
9248 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9249 &isminsettoinfinity, &ismaxsettoinfinity);
9250
9251 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9252 {
9253 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9254
9255 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9256 (*nchgsides)++;
9257 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9258 }
9259
9260 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9261 {
9262 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9263
9264 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9265 (*nchgsides)++;
9266 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9267 }
9268 }
9269 }
9270 else
9271 {
9272 if( !SCIPisInfinity(scip, -minleftactivity) )
9273 {
9274 assert(!SCIPisInfinity(scip, val));
9275 assert(!SCIPisInfinity(scip, lb));
9276 if( SCIPisInfinity(scip, -lb) )
9277 minleftactivity = -SCIPinfinity(scip);
9278 else
9279 minleftactivity += val * lb;
9280 }
9281
9282 if( !SCIPisInfinity(scip, maxleftactivity) )
9283 {
9284 assert(!SCIPisInfinity(scip, val));
9285 assert(!SCIPisInfinity(scip, -ub));
9286 if( SCIPisInfinity(scip,ub) )
9287 maxleftactivity = SCIPinfinity(scip);
9288 else
9289 maxleftactivity += val * ub;
9290 }
9291 }
9292 }
9293 else
9294 {
9295 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9297 SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9298 {
9299 /* change coefficients:
9300 * ai' := min(rhs - maxact, minact - lhs)
9301 * lhs' := lhs - (ai - ai')*ui
9302 * rhs' := rhs - (ai - ai')*li
9303 */
9304
9305 lval = minactivity - consdata->lhs;
9306 rval = consdata->rhs - maxactivity;
9307
9308 /* Try to avoid cancellation, if there are only two variables */
9309 if( consdata->nvars == 2 )
9310 {
9311 SCIP_Real otherval;
9312 otherval = consdata->vals[1-i];
9313
9314 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9315 {
9316 lval = val*ub - consdata->lhs;
9317 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9318 }
9319
9320 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9321 {
9322 rval = consdata->rhs - val*lb;
9323 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9324 }
9325 }
9326
9327 newval = MIN(lval, rval);
9328 assert(SCIPisSumRelGE(scip, newval, val));
9329
9330 /* Try to avoid cancellation in computation of lhs/rhs */
9331 newlhs = consdata->lhs - val * ub;
9332 newlhs += newval * ub;
9333 newrhs = consdata->rhs - val * lb;
9334 newrhs += newval * lb;
9335
9336 if( !SCIPisSumRelEQ(scip, newval, val) )
9337 {
9338 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9339 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9340 minactivity, maxactivity, consdata->lhs, consdata->rhs);
9341
9342 /* update the coefficient and the activity bounds */
9343 if( SCIPisZero(scip, newval) )
9344 {
9345 SCIP_CALL( delCoefPos(scip, cons, i) );
9346 i--;
9347 }
9348 else
9349 {
9350 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9351 }
9352 (*nchgcoefs)++;
9353
9354 /* get the new minimal and maximal activity of the constraint */
9355 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9356 &isminsettoinfinity, &ismaxsettoinfinity);
9357
9358 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9359 {
9360 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9361
9362 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9363 (*nchgsides)++;
9364 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9365 }
9366
9367 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9368 {
9369 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9370
9371 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9372 (*nchgsides)++;
9373 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9374 }
9375 }
9376 }
9377 else
9378 {
9379 if( !SCIPisInfinity(scip, -minleftactivity) )
9380 {
9381 assert(!SCIPisInfinity(scip, -val));
9382 assert(!SCIPisInfinity(scip, -ub));
9383 if( SCIPisInfinity(scip, ub) )
9384 minleftactivity = -SCIPinfinity(scip);
9385 else
9386 minleftactivity += val * ub;
9387 }
9388
9389 if( !SCIPisInfinity(scip, maxleftactivity) )
9390 {
9391 assert(!SCIPisInfinity(scip, -val));
9392 assert(!SCIPisInfinity(scip, lb));
9393 if( SCIPisInfinity(scip, -lb) )
9394 maxleftactivity = SCIPinfinity(scip);
9395 else
9396 maxleftactivity += val * lb;
9397 }
9398 }
9399 }
9400 ++i;
9401 }
9402
9403 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9404 minleftactivity, consdata->rhs);
9405 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9406 maxleftactivity, consdata->lhs);
9407
9408 /* minleft == \infty ==> minactivity == \infty */
9409 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9410 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9411
9412 /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9413 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9414 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9415 * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9416 */
9417 assert(!SCIPisInfinity(scip, minactivity));
9418 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
9419 return SCIP_OKAY;
9420
9421 /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9422 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9423 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9424 * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9425 */
9426 assert(!SCIPisInfinity(scip, -maxactivity));
9427 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
9428 return SCIP_OKAY;
9429
9430 /* correct lhs and rhs by min/max activity of surely non-redundant variables
9431 * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9432 */
9433 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9434 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9435
9436 /* check if the constraint contains variables which are redundant. The reasoning is the following:
9437 * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9438 * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9439 * they can be removed from the constraint.
9440 * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9441 */
9442 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9443 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9444 {
9445 SCIP_Real minleftactivitypart;
9446 SCIP_Real maxleftactivitypart;
9447
9448 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9449
9450 /* try to remove redundant variables from constraint */
9451 i = 0;
9452 while( i < consdata->nvars )
9453 {
9454 var = consdata->vars[i];
9455 minleftactivitypart = 0.0;
9456 maxleftactivitypart = 0.0;
9457 lb = SCIPvarGetLbLocal(var);
9458 ub = SCIPvarGetUbLocal(var);
9459
9460 /* get coefficient and variable's bounds */
9461 val = consdata->vals[i];
9462 assert(!SCIPisZero(scip, val));
9463
9464 /* check sign of coefficient */
9465 if( val >= 0.0 )
9466 {
9467 /* negation of condition above in case of positive val */
9469 SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9470 {
9471 SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9472 SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9473 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9474 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9475
9476 minleftactivitypart = val * lb;
9477 maxleftactivitypart = val * ub;
9478
9479 SCIP_CALL( delCoefPos(scip, cons, i) );
9480 i--;
9481
9482 /* get the new minimal and maximal activity of the constraint */
9483 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9484 &isminsettoinfinity, &ismaxsettoinfinity);
9485
9486 /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9487 * huge contributions
9488 */
9489 assert(isminacttight || SCIPisInfinity(scip, -consdata->lhs));
9490 assert(ismaxacttight || SCIPisInfinity(scip, consdata->rhs));
9491 }
9492 }
9493 else
9494 {
9495 /* negation of condition above in case of negative val */
9497 SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9498 {
9499 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9500 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9501
9502 minleftactivitypart = val * ub;
9503 maxleftactivitypart = val * lb;
9504
9505 SCIP_CALL( delCoefPos(scip, cons, i) );
9506 i--;
9507
9508 /* get the new minimal and maximal activity of the constraint */
9509 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9510 &isminsettoinfinity, &ismaxsettoinfinity);
9511
9512 /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9513 * huge contributions
9514 */
9515 assert(isminacttight || SCIPisInfinity(scip, -consdata->lhs));
9516 assert(ismaxacttight || SCIPisInfinity(scip, consdata->rhs));
9517 }
9518 }
9519
9520 /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9521 * redundant variables could get deleted,
9522 * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9523 * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9524 * we would also delete y2 and as a result we would have gotten infeasibility */
9525 /* adjust lhs and right hand side */
9526 newlhs = consdata->lhs - minleftactivitypart;
9527 newrhs = consdata->rhs - maxleftactivitypart;
9528
9529 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9530 {
9531 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9532 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9533 ++(*nchgsides);
9534 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9535 }
9536 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9537 {
9538 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9539 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9540 ++(*nchgsides);
9541 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9542 }
9543 ++i;
9544 }
9545 }
9546
9547 return SCIP_OKAY;
9548}
9549
9550/** processes equality with only one variable by fixing the variable and deleting the constraint */
9551static
9553 SCIP* scip, /**< SCIP data structure */
9554 SCIP_CONS* cons, /**< linear constraint */
9555 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9556 int* nfixedvars, /**< pointer to count number of fixed variables */
9557 int* ndelconss /**< pointer to count number of deleted constraints */
9558 )
9559{
9560 SCIP_CONSDATA* consdata;
9561 SCIP_VAR* var;
9562 SCIP_Real val;
9563 SCIP_Real fixval;
9564 SCIP_Bool infeasible;
9565 SCIP_Bool fixed;
9566
9567 assert(scip != NULL);
9568 assert(cons != NULL);
9569 assert(cutoff != NULL);
9570 assert(nfixedvars != NULL);
9571 assert(ndelconss != NULL);
9572
9573 consdata = SCIPconsGetData(cons);
9574 assert(consdata != NULL);
9575 assert(consdata->nvars == 1);
9576 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9577
9578 /* calculate the value to fix the variable to */
9579 var = consdata->vars[0];
9580 val = consdata->vals[0];
9581 assert(!SCIPisZero(scip, val));
9582 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9583 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9584 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9585 SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9586
9587 /* fix variable */
9588 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9589 if( infeasible )
9590 {
9591 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9592 *cutoff = TRUE;
9593 return SCIP_OKAY;
9594 }
9595 if( fixed )
9596 (*nfixedvars)++;
9597
9598 /* disable constraint */
9599 SCIP_CALL( SCIPdelCons(scip, cons) );
9600 if( !consdata->upgraded )
9601 (*ndelconss)++;
9602
9603 return SCIP_OKAY;
9604}
9605
9606/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9607static
9609 SCIP* scip, /**< SCIP data structure */
9610 SCIP_CONS* cons, /**< linear constraint */
9611 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9612 int* naggrvars, /**< pointer to count number of aggregated variables */
9613 int* ndelconss /**< pointer to count number of deleted constraints */
9614 )
9615{
9616 SCIP_CONSDATA* consdata;
9617 SCIP_Bool infeasible;
9618 SCIP_Bool redundant;
9619 SCIP_Bool aggregated;
9620
9621 assert(scip != NULL);
9622 assert(cons != NULL);
9623 assert(cutoff != NULL);
9624 assert(naggrvars != NULL);
9625 assert(ndelconss != NULL);
9626
9627 consdata = SCIPconsGetData(cons);
9628 assert(consdata != NULL);
9629 assert(consdata->nvars == 2);
9630 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9631
9632 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9633 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9634 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9635
9636 /* aggregate the equality */
9637 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9638 consdata->rhs, &infeasible, &redundant, &aggregated) );
9639
9640 /* check for infeasibility of aggregation */
9641 if( infeasible )
9642 {
9643 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9644 *cutoff = TRUE;
9645 return SCIP_OKAY;
9646 }
9647
9648 /* count the aggregation */
9649 if( aggregated )
9650 (*naggrvars)++;
9651
9652 /* delete the constraint, if it is redundant */
9653 if( redundant )
9654 {
9655 SCIP_CALL( SCIPdelCons(scip, cons) );
9656
9657 if( !consdata->upgraded )
9658 (*ndelconss)++;
9659 }
9660
9661 return SCIP_OKAY;
9662}
9663
9664/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9665static
9667 SCIP* scip, /**< SCIP data structure */
9668 SCIP_CONSDATA* consdata, /**< linear constraint data */
9669 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9670 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9671 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9672 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9673 )
9674{
9675 SCIP_Real slackvarlb;
9676 SCIP_Real slackvarub;
9677
9678 assert(scip != NULL);
9679 assert(consdata != NULL);
9680 assert(newlhs != NULL);
9681 assert(newrhs != NULL);
9682 assert(!SCIPisInfinity(scip, -consdata->lhs));
9683 assert(!SCIPisInfinity(scip, consdata->rhs));
9684
9685 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9686 slackvarub = SCIPvarGetUbGlobal(slackvar);
9687 if( slackcoef > 0.0 )
9688 {
9689 if( SCIPisInfinity(scip, -slackvarlb) )
9690 *newrhs = SCIPinfinity(scip);
9691 else
9692 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9693 if( SCIPisInfinity(scip, slackvarub) )
9694 *newlhs = -SCIPinfinity(scip);
9695 else
9696 *newlhs = consdata->lhs - slackcoef * slackvarub;
9697 }
9698 else
9699 {
9700 if( SCIPisInfinity(scip, -slackvarlb) )
9701 *newlhs = -SCIPinfinity(scip);
9702 else
9703 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9704 if( SCIPisInfinity(scip, slackvarub) )
9705 *newrhs = SCIPinfinity(scip);
9706 else
9707 *newrhs = consdata->lhs - slackcoef * slackvarub;
9708 }
9709 assert(SCIPisLE(scip, *newlhs, *newrhs));
9710}
9711
9712/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9713 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9714 * is implicitly integral by this constraint
9715 *
9716 * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9717 * can help.
9718 */
9719static
9721 SCIP* scip, /**< SCIP data structure */
9722 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9723 SCIP_CONS* cons, /**< linear constraint */
9724 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9725 int* naggrvars, /**< pointer to count number of aggregated variables */
9726 int* ndelconss /**< pointer to count number of deleted constraints */
9727 )
9728{
9729 SCIP_CONSDATA* consdata;
9730 SCIP_VAR** vars;
9731 SCIP_Real* vals;
9732 SCIP_VARTYPE bestslacktype;
9733 SCIP_VARTYPE slacktype;
9734 SCIP_Real lhs;
9735 SCIP_Real rhs;
9736 SCIP_Real bestslackdomrng;
9737 SCIP_Real minabsval;
9738 SCIP_Real maxabsval;
9739 SCIP_Bool bestremovescons;
9740 SCIP_Bool coefszeroone;
9741 SCIP_Bool coefsintegral;
9742 SCIP_Bool varsintegral;
9743 SCIP_Bool infeasible;
9744 SCIP_Bool samevar;
9745 int supinf; /* counter for infinite contributions to the supremum of a possible
9746 * multi-aggregation
9747 */
9748 int infinf; /* counter for infinite contributions to the infimum of a possible
9749 * multi-aggregation
9750 */
9751 int maxnlocksstay;
9752 int maxnlocksremove;
9753 int bestslackpos;
9754 int bestnlocks;
9755 int ncontvars;
9756 int contvarpos;
9757 int nintvars;
9758 int nimplvars;
9759 int intvarpos;
9760 int v;
9761
9762 assert(scip != NULL);
9763 assert(cons != NULL);
9764 assert(cutoff != NULL);
9765 assert(naggrvars != NULL);
9766
9767 consdata = SCIPconsGetData(cons);
9768 assert(consdata != NULL);
9769 assert(consdata->nvars > 2);
9770 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9771
9772 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9773
9774 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9775 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9776 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9777 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9778 */
9779 lhs = consdata->lhs;
9780 rhs = consdata->rhs;
9781 maxnlocksstay = 0;
9782 if( consdata->nvars == 3 )
9783 {
9784 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9785 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9786 */
9787 maxnlocksremove = 3;
9788 }
9789 else if( consdata->nvars == 4 )
9790 {
9791 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9792 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9793 */
9794 maxnlocksremove = 2;
9795 }
9796 else
9797 {
9798 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9799 maxnlocksremove = 1;
9800 }
9801
9802 /* the locks on this constraint can be ignored */
9803 if( SCIPconsIsChecked(cons) )
9804 {
9805 if( !SCIPisInfinity(scip, -lhs) )
9806 {
9807 maxnlocksstay++;
9808 maxnlocksremove++;
9809 }
9810 if( !SCIPisInfinity(scip, rhs) )
9811 {
9812 maxnlocksstay++;
9813 maxnlocksremove++;
9814 }
9815 }
9816
9817 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9818 vars = consdata->vars;
9819 vals = consdata->vals;
9820 bestslackpos = -1;
9821 bestslacktype = SCIP_VARTYPE_BINARY;
9822 bestnlocks = INT_MAX;
9823 bestremovescons = FALSE;
9824 bestslackdomrng = 0.0;
9825 coefszeroone = TRUE;
9826 coefsintegral = TRUE;
9827 varsintegral = TRUE;
9828 ncontvars = 0;
9829 contvarpos = -1;
9830 nintvars = 0;
9831 nimplvars = 0;
9832 intvarpos = -1;
9833 minabsval = SCIPinfinity(scip);
9834 maxabsval = -1.0;
9835 for( v = 0; v < consdata->nvars; ++v )
9836 {
9837 SCIP_VAR* var;
9838 SCIP_Real val;
9839 SCIP_Real absval;
9840 SCIP_Real varlb;
9841 SCIP_Real varub;
9842 SCIP_Bool iscont;
9843 int nlocks;
9844
9845 assert(vars != NULL);
9846 assert(vals != NULL);
9847
9848 var = vars[v];
9849 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9851 varlb = SCIPvarGetLbGlobal(var);
9852 varub = SCIPvarGetUbGlobal(var);
9853
9854 val = vals[v];
9855 absval = REALABS(val);
9856 assert(SCIPisPositive(scip, absval));
9857
9858 /* calculate minimal and maximal absolute value */
9859 if( absval < minabsval )
9860 minabsval = absval;
9861 if( absval > maxabsval )
9862 maxabsval = absval;
9863
9864 /* do not try to multi aggregate, when numerical bad */
9865 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9866 return SCIP_OKAY;
9867
9868 slacktype = SCIPvarGetType(var);
9869 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9870 coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9871 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9872 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9873
9874 /* update candidates for continuous -> implint and integer -> implint conversion */
9875 if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9876 {
9877 ncontvars++;
9878 contvarpos = v;
9879 }
9880 else if( slacktype == SCIP_VARTYPE_IMPLINT )
9881 {
9882 ++nimplvars;
9883 }
9884 else if( slacktype == SCIP_VARTYPE_INTEGER )
9885 {
9886 nintvars++;
9887 intvarpos = v;
9888 }
9889
9890 /* check, if variable is already fixed or aggregated */
9891 if( !SCIPvarIsActive(var) )
9892 continue;
9893
9894 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9896
9897 if( nlocks > maxnlocksremove )
9898 continue;
9899
9900 /* check, if variable can be used as a slack variable */
9901 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9903 {
9904 SCIP_Bool better;
9905 SCIP_Bool equal;
9906 SCIP_Real slackdomrng;
9907
9908 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9909 slackdomrng = SCIPinfinity(scip);
9910 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9911 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9912 return SCIP_OKAY;
9913 else
9914 {
9915 slackdomrng = (varub - varlb)*absval;
9916 assert(!SCIPisInfinity(scip, slackdomrng));
9917 }
9918 equal = FALSE;
9919 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9920 if( !better && slacktype == bestslacktype )
9921 {
9922 better = (nlocks < bestnlocks);
9923 if( nlocks == bestnlocks && !bestremovescons )
9924 {
9925 better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9926 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9927 }
9928 }
9929
9930 if( better || equal )
9931 {
9932 SCIP_Real minresactivity;
9933 SCIP_Real maxresactivity;
9934 SCIP_Real newlhs;
9935 SCIP_Real newrhs;
9936 SCIP_Bool removescons;
9937 SCIP_Bool ismintight;
9938 SCIP_Bool ismaxtight;
9939 SCIP_Bool isminsettoinfinity;
9940 SCIP_Bool ismaxsettoinfinity;
9941
9942 /* check if the constraint becomes redundant after multi-aggregation */
9943 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9944 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
9945
9946 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9947 * activity
9948 */
9949 if( !ismintight || !ismaxtight )
9950 continue;
9951
9952 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9953 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9954
9955 /* check resactivities for reliability */
9956 if( removescons )
9957 {
9958 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9959 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9960
9961 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9962 && SCIPisFeasLE(scip, newlhs, minresactivity))
9963 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9964
9965 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9966 }
9967
9968 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9969 if( conshdlrdata->multaggrremove && !removescons )
9970 continue;
9971
9972 /* prefer variables that make the constraints redundant */
9973 if( bestremovescons && !removescons )
9974 continue;
9975
9976 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9977 * other constraints
9978 */
9979 if( !removescons && nlocks > maxnlocksstay )
9980 continue;
9981
9982 better = better || (!bestremovescons && removescons);
9983 if( better )
9984 {
9985 bestslackpos = v;
9986 bestslacktype = slacktype;
9987 bestnlocks = nlocks;
9988 bestslackdomrng = slackdomrng;
9989 bestremovescons = removescons;
9990 }
9991 }
9992 }
9993 }
9994
9995 /* if all coefficients and variables are integral, the right hand side must also be integral */
9996 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9997 {
9998 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
10000 *cutoff = TRUE;
10001 return SCIP_OKAY;
10002 }
10003
10004 supinf = 0;
10005 infinf = 0;
10006 samevar = FALSE;
10007
10008 /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
10009 for( v = 0; v < consdata->nvars; ++v )
10010 {
10011 if( v != bestslackpos )
10012 {
10013 if( SCIPisPositive(scip, consdata->vals[v]) )
10014 {
10015 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10016 {
10017 ++supinf;
10018 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10019 {
10020 ++infinf;
10021 samevar = TRUE;
10022 }
10023 }
10024 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10025 ++infinf;
10026 }
10027 else if( SCIPisNegative(scip, consdata->vals[v]) )
10028 {
10029 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10030 {
10031 ++supinf;
10032 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10033 {
10034 ++infinf;
10035 samevar = TRUE;
10036 }
10037 }
10038 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10039 ++infinf;
10040 }
10041 }
10042 }
10043 assert(!samevar || (supinf > 0 && infinf > 0));
10044
10045 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10046 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10047 if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
10048 {
10049 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10050 return SCIP_OKAY;
10051 }
10052
10053 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
10054 * we cannot aggregate the variable, because the integrality condition would get lost
10055 * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
10056 * loose the integrality condition for this variable.
10057 */
10058 if( bestslackpos >= 0
10059 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
10060 || (coefsintegral && varsintegral && nimplvars == 0)) )
10061 {
10062 SCIP_VAR* slackvar;
10063 SCIP_Real* scalars;
10064 SCIP_Real slackcoef;
10065 SCIP_Real aggrconst;
10066 SCIP_Real newlhs;
10067 SCIP_Real newrhs;
10068 SCIP_Bool aggregated;
10069
10070 /* we found a slack variable that only occurs in at most one other constraint:
10071 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
10072 */
10073 assert(bestslackpos < consdata->nvars);
10074
10075 /* do not multi aggregate binary variables */
10076 if( SCIPvarIsBinary(vars[bestslackpos]) )
10077 return SCIP_OKAY;
10078
10079 /* convert equality into inequality by deleting the slack variable:
10080 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
10081 */
10082 slackvar = vars[bestslackpos];
10083 slackcoef = vals[bestslackpos];
10084 assert(!SCIPisZero(scip, slackcoef));
10085 aggrconst = consdata->rhs/slackcoef;
10086
10087 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
10088 assert(SCIPisLE(scip, newlhs, newrhs));
10089 SCIP_CALL( chgLhs(scip, cons, newlhs) );
10090 SCIP_CALL( chgRhs(scip, cons, newrhs) );
10091 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
10092
10093 /* allocate temporary memory */
10094 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
10095
10096 /* set up the multi-aggregation */
10097 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
10098 for( v = 0; v < consdata->nvars; ++v )
10099 {
10100 scalars[v] = -consdata->vals[v]/slackcoef;
10101 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
10102 }
10103 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
10104 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
10105 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
10106
10107 /* perform the multi-aggregation */
10108 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10109 &infeasible, &aggregated) );
10110 assert(aggregated);
10111
10112 /* free temporary memory */
10114
10115 /* check for infeasible aggregation */
10116 if( infeasible )
10117 {
10118 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10119 *cutoff = TRUE;
10120 return SCIP_OKAY;
10121 }
10122
10123 (*naggrvars)++;
10124
10125 /* delete the constraint if it became redundant */
10126 if( bestremovescons )
10127 {
10128 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10129 SCIP_CALL( SCIPdelCons(scip, cons) );
10130
10131 if( !consdata->upgraded )
10132 (*ndelconss)++;
10133 }
10134 }
10135 else if( ncontvars == 1 )
10136 {
10137 SCIP_VAR* var;
10138
10139 assert(0 <= contvarpos && contvarpos < consdata->nvars);
10140 var = vars[contvarpos];
10142
10143 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10144 {
10145 /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10146 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10147 {
10148 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10149 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10152 if( infeasible )
10153 {
10154 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10155 *cutoff = TRUE;
10156
10157 return SCIP_OKAY;
10158 }
10159 }
10160 /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10161 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10162 else if( !SCIPdoNotAggr(scip) )
10163 {
10164 SCIP_VAR* newvar;
10165 SCIP_Real absval;
10166 char newvarname[SCIP_MAXSTRLEN];
10167 SCIP_Bool redundant;
10168 SCIP_Bool aggregated;
10169
10170 absval = REALABS(vals[contvarpos]);
10171
10172 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10173
10174 /* create new implicit variable for aggregation */
10175 SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10177
10178 /* add new variable to problem */
10179 SCIP_CALL( SCIPaddVar(scip, newvar) );
10180
10181#ifdef WITH_DEBUG_SOLUTION
10182 if( SCIPdebugIsMainscip(scip) )
10183 {
10184 SCIP_Real varval;
10185 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10186 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10187 }
10188#endif
10189
10190 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10191 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10192 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10193
10194 /* aggregate continuous and implicit variable */
10195 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10196
10197 if( infeasible )
10198 {
10199 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10201 *cutoff = TRUE;
10202
10203 /* release implicit variable */
10204 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10205
10206 return SCIP_OKAY;
10207 }
10208
10209 /* release implicit variable */
10210 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10211
10212 if( aggregated )
10213 (*naggrvars)++;
10214 else
10215 return SCIP_OKAY;
10216 }
10217
10218 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10219 * again
10220 */
10221 consdata->boundstightened = 0;
10222 consdata->rangedrowpropagated = 0;
10223 consdata->presolved = FALSE;
10224 }
10225 }
10226 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10227 {
10228 SCIP_VAR* var;
10229
10230 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10231 * -> we don't convert integers into implints if the row is a 0/1-row
10232 */
10233 assert(varsintegral);
10234 assert(0 <= intvarpos && intvarpos < consdata->nvars);
10235 var = vars[intvarpos];
10237
10238 if( coefsintegral
10239 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10240 && SCIPisFeasIntegral(scip, consdata->rhs) )
10241 {
10242 /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10243 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10246 if( infeasible )
10247 {
10248 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10249 *cutoff = TRUE;
10250
10251 return SCIP_OKAY;
10252 }
10253 }
10254 }
10255
10256 return SCIP_OKAY;
10257}
10258
10259/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10260static
10262 SCIP* scip, /**< SCIP data structure */
10263 SCIP_CONSDATA* consdata, /**< linear constraint data */
10264 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10265 * objective function */
10266 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10267 * this constraint */
10268 )
10269{
10270 SCIP_VAR** vars;
10271 SCIP_VAR* var;
10272 SCIP_Real objval;
10273 SCIP_Bool negated;
10274 int nvars;
10275 int v;
10276
10277 vars = consdata->vars;
10278 nvars = consdata->nvars;
10279
10280 assert(vars != NULL);
10281
10282 for( v = 0; v < nvars; ++v )
10283 {
10284 negated = FALSE;
10285 var = vars[v];
10286 assert(var != NULL);
10287
10288 if( SCIPvarIsNegated(var) )
10289 {
10290 negated = TRUE;
10292 assert(var != NULL);
10293 }
10294
10296
10297 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10298 * function
10299 */
10300 if( SCIPisZero(scip, objval) )
10301 return FALSE;
10302 else
10303 {
10304 SCIP_Real val;
10305
10306 val = consdata->vals[v];
10307
10308 if( negated )
10309 {
10310 if( v == 0 )
10311 {
10312 /* the first variable defines the scale */
10313 (*scale) = val / -objval;
10314
10315 (*offset) += val;
10316 }
10317 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10318 (*offset) += val;
10319 else
10320 return FALSE;
10321 }
10322 else if( v == 0 )
10323 {
10324 /* the first variable defines the scale */
10325 (*scale) = val / objval;
10326 }
10327 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10328 return FALSE;
10329 }
10330 }
10331
10332 return TRUE;
10333}
10334
10335/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10336 * objective coefficients and add an objective offset
10337 */
10338static
10340 SCIP* scip, /**< SCIP data structure */
10341 SCIP_CONS* cons, /**< linear equation constraint */
10342 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10343 )
10344{
10345 SCIP_CONSDATA* consdata;
10346 SCIP_Real offset;
10347 SCIP_Real scale;
10348 SCIP_Bool applicable;
10349 int nobjvars;
10350 int nvars;
10351 int v;
10352
10353 assert(scip != NULL);
10354 assert(cons != NULL);
10355 assert(conshdlrdata != NULL);
10356
10357 consdata = SCIPconsGetData(cons);
10358 assert(consdata != NULL);
10359 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10360
10361 nvars = consdata->nvars;
10362 nobjvars = SCIPgetNObjVars(scip);
10363
10364 /* check if the linear equality constraints does not have more variables than the objective function */
10365 if( nvars > nobjvars || nvars == 0 )
10366 return SCIP_OKAY;
10367
10368 /* check for allowance of algorithm */
10369 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10370 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10371 return SCIP_OKAY;
10372
10373 offset = consdata->rhs;
10374 scale = 1.0;
10375
10376 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10377 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10378
10379 if( applicable )
10380 {
10381 SCIP_VAR** vars;
10382
10383 vars = consdata->vars;
10384 assert(vars != NULL);
10385
10386 offset /= scale;
10387
10388 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10389 SCIPconsGetName(cons), consdata->rhs, offset);
10390
10391 /* make equality a model constraint to ensure optimality in this direction */
10394
10395 /* set all objective coefficient to zero */
10396 for( v = 0; v < nvars; ++v )
10397 {
10398 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10399 }
10400
10401 /* add an objective offset */
10402 SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10403 }
10404
10405 return SCIP_OKAY;
10406}
10407
10408/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10409static
10411 SCIP* scip, /**< SCIP data structure */
10412 SCIP_CONS* cons, /**< constraint */
10413 SCIP_Real primalbound /**< feasible primal bound */
10414 )
10415{
10416 SCIP_Real cutoffbound;
10417
10418 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10419 * accepted
10420 */
10421 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10422
10423 if( cutoffbound < SCIPgetCutoffbound(scip) )
10424 {
10425 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10426
10427 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10428 }
10429 else
10430 {
10431 SCIP_CONSDATA* consdata;
10432
10433 consdata = SCIPconsGetData(cons);
10434 assert(consdata != NULL);
10435
10436 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10437 * resulted from one side
10438 */
10439 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10440 {
10441 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10442 * propagation
10443 */
10446 }
10447 }
10448
10449 return SCIP_OKAY;
10450}
10451
10452/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10453 * constraint enters the LP by setting the initial and separated flag to FALSE
10454 */
10455static
10457 SCIP* scip, /**< SCIP data structure */
10458 SCIP_CONS* cons, /**< linear constraint */
10459 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10460 )
10461{
10462 SCIP_CONSDATA* consdata;
10463 SCIP_Real offset;
10464 SCIP_Real scale;
10465 SCIP_Bool applicable;
10466 int nobjvars;
10467 int nvars;
10468
10469 assert(scip != NULL);
10470 assert(cons != NULL);
10471 assert(conshdlrdata != NULL);
10472
10473 consdata = SCIPconsGetData(cons);
10474 assert(consdata != NULL);
10475
10476 /* ignore equalities since these are covered by the method checkPartialObjective() */
10477 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10478 return SCIP_OKAY;
10479
10480 nvars = consdata->nvars;
10481 nobjvars = SCIPgetNObjVars(scip);
10482
10483 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10484 * initial and/or separated flag is set to FALSE
10485 */
10486 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10487 return SCIP_OKAY;
10488
10489 offset = 0.0;
10490 scale = 1.0;
10491
10492 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10493 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10494 */
10495 if( nobjvars == 0 )
10496 return SCIP_OKAY;
10497
10498 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10499 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10500
10501 if( applicable )
10502 {
10503 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10504 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10505
10506 assert(scale != 0.0);
10507
10508 if( scale > 0.0 )
10509 {
10510 if( conshdlrdata->detectcutoffbound && rhsfinite )
10511 {
10512 SCIP_Real primalbound;
10513
10514 primalbound = (consdata->rhs - offset) / scale;
10515
10516 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10517 SCIPconsGetName(cons), primalbound);
10518
10519 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10520 }
10521
10522 if( conshdlrdata->detectlowerbound && lhsfinite )
10523 {
10524 SCIP_Real lowerbound;
10525
10526 lowerbound = (consdata->lhs - offset) / scale;
10527
10528 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10529 SCIPconsGetName(cons), lowerbound);
10530
10532 }
10533
10534 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10535 (conshdlrdata->detectlowerbound && !rhsfinite) )
10536 {
10537 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10540 }
10541 }
10542 else
10543 {
10544 if( conshdlrdata->detectlowerbound && rhsfinite )
10545 {
10546 SCIP_Real lowerbound;
10547
10548 lowerbound = (consdata->rhs - offset) / scale;
10549
10550 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10551 SCIPconsGetName(cons), lowerbound);
10552
10554 }
10555
10556 if( conshdlrdata->detectcutoffbound && lhsfinite )
10557 {
10558 SCIP_Real primalbound;
10559
10560 primalbound = (consdata->lhs - offset) / scale;
10561
10562 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10563 SCIPconsGetName(cons), primalbound);
10564
10565 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10566 }
10567
10568 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10569 (conshdlrdata->detectlowerbound && !lhsfinite) )
10570 {
10571 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10574 }
10575 }
10576 }
10577
10578 return SCIP_OKAY;
10579}
10580
10581/** converts special equalities */
10582static
10584 SCIP* scip, /**< SCIP data structure */
10585 SCIP_CONS* cons, /**< linear constraint */
10586 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10587 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10588 int* nfixedvars, /**< pointer to count number of fixed variables */
10589 int* naggrvars, /**< pointer to count number of aggregated variables */
10590 int* ndelconss /**< pointer to count number of deleted constraints */
10591 )
10592{
10593 SCIP_CONSDATA* consdata;
10594
10595 assert(scip != NULL);
10596 assert(cons != NULL);
10597 assert(conshdlrdata != NULL);
10598 assert(cutoff != NULL);
10599 assert(nfixedvars != NULL);
10600 assert(naggrvars != NULL);
10601 assert(ndelconss != NULL);
10602
10603 consdata = SCIPconsGetData(cons);
10604 assert(consdata != NULL);
10605 assert(consdata->removedfixings);
10606
10607 /* do nothing on inequalities */
10608 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10609 return SCIP_OKAY;
10610
10611 /* depending on the number of variables, call a special conversion method */
10612 if( consdata->nvars == 1 )
10613 {
10614 /* fix variable */
10615 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10616 }
10617 else if( consdata->nvars == 2 )
10618 {
10619 /* aggregate one of the variables */
10620 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10621 }
10622 else
10623 {
10624 /* check if the equality is part of the objective function */
10625 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10626
10627 /* try to multi-aggregate one of the variables */
10628 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10629 }
10630
10631 return SCIP_OKAY;
10632}
10633
10634/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10635 * integral
10636 */
10637static
10639 SCIP* scip, /**< SCIP data structure */
10640 SCIP_CONSDATA* consdata, /**< linear constraint */
10641 int pos, /**< position of variable to be left out */
10642 SCIP_Real val /**< value to divide the coefficients by */
10643 )
10644{
10645 int v;
10646
10647 assert(scip != NULL);
10648 assert(consdata != NULL);
10649 assert(0 <= pos && pos < consdata->nvars);
10650
10651 for( v = 0; v < consdata->nvars; ++v )
10652 {
10653 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10654 return FALSE;
10655 }
10656
10657 return TRUE;
10658}
10659
10660/** 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$,
10661 * 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$
10662 */
10663static
10665 SCIP* scip, /**< SCIP data structure */
10666 SCIP_Real side, /**< lhs or rhs */
10667 SCIP_Real val, /**< coefficient */
10668 SCIP_Real minresactivity, /**< minimal residual activity */
10669 SCIP_Real maxresactivity, /**< maximal residual activity */
10670 SCIP_Real* minval, /**< pointer to store calculated minval */
10671 SCIP_Real* maxval /**< pointer to store calculated maxval */
10672 )
10673{
10674 assert(scip != NULL);
10675 assert(minval != NULL);
10676 assert(maxval != NULL);
10677
10678 if( val > 0.0 )
10679 {
10680 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10681 *minval = -maxresactivity;
10682 else
10683 *minval = (side - maxresactivity)/val;
10684
10685 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10686 *maxval = -minresactivity;
10687 else
10688 *maxval = (side - minresactivity)/val;
10689 }
10690 else
10691 {
10692 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10693 *minval = minresactivity;
10694 else
10695 *minval = (side - minresactivity)/val;
10696
10697 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10698 *maxval = maxresactivity;
10699 else
10700 *maxval = (side - maxresactivity)/val;
10701 }
10702}
10703
10704
10705/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10706 * linear inequality
10707 */
10708static
10710 SCIP* scip, /**< SCIP data structure */
10711 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10712 SCIP_CONS* cons, /**< linear constraint */
10713 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10714 int* nfixedvars, /**< pointer to count number of fixed variables */
10715 int* naggrvars, /**< pointer to count number of aggregated variables */
10716 int* ndelconss /**< pointer to count number of deleted constraints */
10717 )
10718{
10719 SCIP_CONSDATA* consdata;
10720 SCIP_Bool lhsexists;
10721 SCIP_Bool rhsexists;
10722 SCIP_Bool bestisint;
10723 SCIP_Bool bestislhs;
10724 SCIP_Real minabsval;
10725 SCIP_Real maxabsval;
10726 int bestpos;
10727 int i;
10728 int maxotherlocks;
10729
10730 assert(scip != NULL);
10731 assert(cons != NULL);
10732 assert(cutoff != NULL);
10733 assert(nfixedvars != NULL);
10734 assert(naggrvars != NULL);
10735 assert(ndelconss != NULL);
10736
10737 /* only process checked constraints (for which the locks are increased);
10738 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10739 * dualfix presolver
10740 */
10741 if( !SCIPconsIsChecked(cons) )
10742 return SCIP_OKAY;
10743
10744 consdata = SCIPconsGetData(cons);
10745 assert(consdata != NULL);
10746
10747 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10748 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10749
10750 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10751 * can use it safely for aggregation and break the search loop
10752 */
10753 bestpos = -1;
10754 bestisint = TRUE;
10755 bestislhs = FALSE;
10756
10757 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10758 * everything else would produce fill-in. Exceptions:
10759 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10760 * produced.
10761 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10762 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10763 * six nonzeros (two variables per substitution).
10764 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10765 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10766 * six nonzeros (three variables per substitution). God exists!
10767 */
10768 if( consdata->nvars <= 2 )
10769 maxotherlocks = INT_MAX;
10770 else if( consdata->nvars == 3 )
10771 maxotherlocks = 3;
10772 else if( consdata->nvars == 4 )
10773 maxotherlocks = 2;
10774 else
10775 maxotherlocks = 1;
10776
10777 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10778 if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10779 maxotherlocks++;
10780
10781 minabsval = SCIPinfinity(scip);
10782 maxabsval = -1.0;
10783 for( i = 0; i < consdata->nvars && bestisint; ++i )
10784 {
10785 SCIP_VAR* var;
10786 SCIP_Bool isint;
10787 SCIP_Real val;
10788 SCIP_Real absval;
10789 SCIP_Real obj;
10790 SCIP_Real lb;
10791 SCIP_Real ub;
10792 SCIP_Bool agglhs;
10793 SCIP_Bool aggrhs;
10794
10795 val = consdata->vals[i];
10796 absval = REALABS(val);
10797
10798 /* calculate minimal and maximal absolute value */
10799 if( absval < minabsval )
10800 minabsval = absval;
10801 if( absval > maxabsval )
10802 maxabsval = absval;
10803
10804 /* do not try to multi aggregate, when numerical bad */
10805 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10806 return SCIP_OKAY;
10807
10808 var = consdata->vars[i];
10810
10811 /* if we already found a candidate, skip integers */
10812 if( bestpos >= 0 && isint )
10813 continue;
10814
10815 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10816 * active, fixed, or single-aggregated with another binary variable
10817 */
10818 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10819 continue;
10820
10822 continue;
10823
10824 val = consdata->vals[i];
10826 lb = SCIPvarGetLbGlobal(var);
10827 ub = SCIPvarGetUbGlobal(var);
10828
10829 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10830 *
10831 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10832 * - constraint is the only one that forbids fixing the variable to its lower bound
10833 * - 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
10834 *
10835 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10836 * - constraint is the only one that forbids fixing the variable to its upper bound
10837 * - 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
10838 *
10839 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10840 * - constraint is the only one that forbids fixing the variable to its upper bound
10841 * - 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
10842 *
10843 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10844 * - constraint is the only one that forbids fixing the variable to its lower bound
10845 * - 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
10846 *
10847 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10848 * of all x_j
10849 * furthermore: we only want to apply this, if no fill-in will be produced
10850 */
10851 agglhs = lhsexists
10853 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10855 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10856 aggrhs = rhsexists
10858 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10860 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10861 if( agglhs || aggrhs )
10862 {
10863 SCIP_Real minresactivity;
10864 SCIP_Real maxresactivity;
10865 SCIP_Real minval;
10866 SCIP_Real maxval;
10867 SCIP_Bool ismintight;
10868 SCIP_Bool ismaxtight;
10869 SCIP_Bool isminsettoinfinity;
10870 SCIP_Bool ismaxsettoinfinity;
10871
10872 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10873 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10874 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
10875 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10876
10877 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10878 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10879 * This is needed, because we do not want to rely on relaxed finite resactivities.
10880 */
10881 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
10882
10883 if( agglhs )
10884 {
10885 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10886 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10887
10888 assert(SCIPisLE(scip, minval, maxval));
10889 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10890 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10891 {
10892 SCIP_Real oldmaxresactivity;
10893 SCIP_Real oldminresactivity;
10894 SCIP_Bool recalculated;
10895
10896 recalculated = FALSE;
10897 oldmaxresactivity = maxresactivity;
10898 oldminresactivity = minresactivity;
10899
10900 /* check minresactivity for reliability */
10901 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10902 {
10903 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10904 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10905 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10906 }
10907
10908 /* check maxresactivity for reliability */
10909 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10910 {
10911 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10912 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10913 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10914 }
10915
10916 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10917 if( recalculated )
10918 {
10919 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10920
10921 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10922 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10923
10924 assert(SCIPisLE(scip, minval, maxval));
10925 }
10926
10927 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10928 {
10929 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10930 * in the multi-aggregation
10931 */
10932 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10933 {
10934 bestpos = i;
10935 bestisint = isint;
10936 bestislhs = TRUE;
10937 continue; /* no need to also look at the right hand side */
10938 }
10939 }
10940 }
10941 }
10942
10943 if( aggrhs )
10944 {
10945 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10946 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10947
10948 assert(SCIPisLE(scip,minval,maxval));
10949 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10950 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10951 {
10952 SCIP_Real oldmaxresactivity;
10953 SCIP_Real oldminresactivity;
10954 SCIP_Bool recalculated;
10955
10956 recalculated = FALSE;
10957 oldmaxresactivity = maxresactivity;
10958 oldminresactivity = minresactivity;
10959
10960 /* check minresactivity for reliability */
10961 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10962 {
10963 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10964 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10965 }
10966
10967 /* check maxresactivity for reliability */
10968 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10969 {
10970 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10971 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10972 }
10973
10974 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10975 if( recalculated )
10976 {
10977 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10978 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10979 assert(SCIPisLE(scip,minval,maxval));
10980 }
10981
10982 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10983 {
10984 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10985 * in the multi-aggregation
10986 */
10987 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10988 {
10989 bestpos = i;
10990 bestisint = isint;
10991 bestislhs = FALSE;
10992 }
10993 }
10994 }
10995 }
10996 }
10997 }
10998
10999 if( bestpos >= 0 )
11000 {
11001 SCIP_VAR** aggrvars;
11002 SCIP_Real* aggrcoefs;
11003 SCIP_Real aggrconst;
11004 SCIP_VAR* bestvar;
11005 SCIP_Real bestval;
11006 SCIP_Real epsilon;
11007 int naggrs;
11008 int j;
11009 SCIP_Bool infeasible;
11010 SCIP_Bool aggregated;
11011 SCIP_Bool samevar;
11012 int supinf; /* counter for infinite contributions to the supremum of a possible
11013 * multi-aggregation
11014 */
11015 int infinf; /* counter for infinite contributions to the infimum of a possible
11016 * multi-aggregation
11017 */
11018
11019 assert(!bestislhs || lhsexists);
11020 assert(bestislhs || rhsexists);
11021
11022 bestvar = consdata->vars[bestpos];
11023 bestval = consdata->vals[bestpos];
11024 assert(bestisint ==
11026
11027 /* allocate temporary memory */
11028 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
11029 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
11030
11031 /* set up the multi-aggregation */
11033 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
11034 naggrs = 0;
11035 supinf = 0;
11036 infinf = 0;
11037 samevar = FALSE;
11038 epsilon = SCIPepsilon(scip);
11039
11040 for( j = 0; j < consdata->nvars; ++j )
11041 {
11042 if( j != bestpos )
11043 {
11044 SCIP_Real absaggrcoef;
11045
11046 aggrvars[naggrs] = consdata->vars[j];
11047 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
11048 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
11049
11050 absaggrcoef = REALABS(aggrcoefs[naggrs]);
11051
11052 /* do not try to multi aggregate, when numerical bad */
11053 if( absaggrcoef < epsilon )
11054 {
11055 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
11056
11057 /* free temporary memory */
11058 SCIPfreeBufferArray(scip, &aggrcoefs);
11059 SCIPfreeBufferArray(scip, &aggrvars);
11060
11061 return SCIP_OKAY;
11062 }
11063
11064 if( bestisint )
11065 {
11066 /* coefficient must be integral: round it to exact integral value */
11067 assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
11068 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
11069 }
11070
11071 if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
11072 {
11073 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11074 {
11075 ++supinf;
11076 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11077 {
11078 ++infinf;
11079 samevar = TRUE;
11080 }
11081 }
11082 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11083 ++infinf;
11084 }
11085 else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
11086 {
11087 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11088 {
11089 ++supinf;
11090 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11091 {
11092 ++infinf;
11093 samevar = TRUE;
11094 }
11095 }
11096 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11097 ++infinf;
11098 }
11099
11100 naggrs++;
11101 }
11102 }
11103 assert(!samevar || (supinf > 0 && infinf > 0));
11104
11105 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11106 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11107 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
11108 assert(naggrs == consdata->nvars-1);
11109
11110 /* right hand side must be integral: round it to exact integral value */
11111 if( bestisint )
11112 {
11113 assert(SCIPisIntegral(scip, aggrconst));
11114 aggrconst = SCIPfloor(scip, aggrconst+0.5);
11115 }
11116
11117 aggregated = FALSE;
11118 infeasible = FALSE;
11119
11120 /* perform the multi-aggregation */
11121 if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11122 {
11123 /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11124 * also convertLongEquality() early termination due to coefficients
11125 */
11126 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11127
11128 /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11129 * the implicitness might rely on the constraint and the integrality of bestvar
11130 */
11131 if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11132 {
11133 SCIP_Bool infeasiblevartypechg;
11134
11135 for( j = 0; j < naggrs; ++j)
11136 {
11137 /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11138 * lead to infeasibility
11139 */
11140 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT )
11141 {
11142 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
11143 assert(!infeasiblevartypechg);
11144 }
11145 }
11146 }
11147 }
11148 else
11149 {
11150 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11151 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11152 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11153 }
11154 /* free temporary memory */
11155 SCIPfreeBufferArray(scip, &aggrcoefs);
11156 SCIPfreeBufferArray(scip, &aggrvars);
11157
11158 /* check for infeasible aggregation */
11159 if( infeasible )
11160 {
11161 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11162 *cutoff = TRUE;
11163 return SCIP_OKAY;
11164 }
11165
11166 /* delete the constraint, if the aggregation was successful */
11167 if( aggregated )
11168 {
11169 SCIP_CALL( SCIPdelCons(scip, cons) );
11170
11171 if( !consdata->upgraded )
11172 (*ndelconss)++;
11173 (*naggrvars)++;
11174 }
11175 else
11176 {
11177 SCIPdebugMsg(scip, "aggregation non successful!\n");
11178 }
11179 }
11180
11181 return SCIP_OKAY;
11182}
11183
11184#define BINWEIGHT 1
11185#define INTWEIGHT 4
11186#define CONTWEIGHT 8
11187
11188/** gets weight for variable in a "weighted number of variables" sum */
11189static
11191 SCIP_VAR* var /**< variable to get weight for */
11192 )
11193{
11194 switch( SCIPvarGetType(var) )
11195 {
11197 return BINWEIGHT;
11200 return INTWEIGHT;
11202 return CONTWEIGHT;
11203 default:
11204 SCIPerrorMessage("invalid variable type\n");
11205 SCIPABORT();
11206 return 0; /*lint !e527*/
11207 }
11208}
11209
11210/** tries to aggregate variables in equations a^Tx = lhs
11211 * in case there are at most two binary variables with an odd coefficient and all other
11212 * variables are not continuous and have an even coefficient then:
11213 * - exactly one odd binary variables
11214 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11215 * - lhs is odd -> y = 1
11216 * - lhs is even -> y = 0
11217 * - exactly two odd binary variables
11218 * aggregate the two binary variables with odd coefficient
11219 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11220 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11221 */
11222static
11224 SCIP* scip, /**< SCIP data structure */
11225 SCIP_CONS* cons, /**< linear constraint */
11226 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11227 int* nfixedvars, /**< pointer to count number of fixed variables */
11228 int* naggrvars /**< pointer to count number of aggregated variables */
11229 )
11230{ /*lint --e{715}*/
11231 SCIP_CONSDATA* consdata;
11232 SCIP_Bool success;
11233
11234 assert( scip != NULL );
11235 assert( cons != NULL );
11236
11237 consdata = SCIPconsGetData(cons);
11238 assert( consdata != NULL );
11239
11240 /* check if the linear constraint is an equation with integral right hand side */
11241 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11242 return SCIP_OKAY;
11243
11244 /* try to fix and aggregated variables until nothing is possible anymore */
11245 do
11246 {
11247 int v;
11248 int nvars;
11249 SCIP_VAR** vars;
11250 SCIP_Real* vals;
11251 SCIP_Real lhs;
11252 SCIP_Bool lhsodd;
11253
11254 SCIP_Bool infeasible;
11255 SCIP_Bool fixed;
11256 SCIP_Bool aggregated;
11257 SCIP_Bool redundant;
11258
11259 SCIP_VAR* var1;
11260 SCIP_VAR* var2;
11261 int noddvars;
11262
11263 success = FALSE;
11264
11265 lhs = consdata->lhs;
11266 vars = consdata->vars;
11267 vals = consdata->vals;
11268 nvars = consdata->nvars;
11269
11270 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11271
11272 var1 = NULL;
11273 var2 = NULL;
11274 noddvars = 0;
11275
11276 /* search for binary variables with an odd coefficient */
11277 for( v = 0; v < nvars && noddvars < 3; ++v )
11278 {
11279 SCIP_Longint val;
11280
11281 /* all coefficients and variables have to be integral */
11283 return SCIP_OKAY;
11284
11285 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11286 if( val % 2 != 0 )
11287 {
11288 /* the odd values have to belong to binary variables */
11289 if( !SCIPvarIsBinary(vars[v]) )
11290 return SCIP_OKAY;
11291
11292 if( noddvars == 0 )
11293 var1 = vars[v];
11294 else
11295 var2 = vars[v];
11296
11297 noddvars++;
11298 }
11299 }
11300
11301 /* check lhs is odd or even */
11302 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11303
11304 if( noddvars == 1 )
11305 {
11306 assert( var1 != NULL );
11307
11308 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11309 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11310
11311 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11312
11313 /* check for infeasibility of fixing */
11314 if( infeasible )
11315 {
11316 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11317 *cutoff = TRUE;
11318 return SCIP_OKAY;
11319 }
11320
11321 if( fixed )
11322 {
11323 SCIPdebugMsg(scip, " -> feasible fixing\n");
11324 (*nfixedvars)++;
11325 success = TRUE;
11326 }
11327 }
11328 else if( noddvars == 2 )
11329 {
11330 assert( var1 != NULL );
11331 assert( var2 != NULL );
11332
11333 /* aggregate the two variables with odd coefficient
11334 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11335 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11336 */
11337 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11338 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11339
11340 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11341 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11342
11343 /* check for infeasibility of aggregation */
11344 if( infeasible )
11345 {
11346 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11347 *cutoff = TRUE;
11348 return SCIP_OKAY;
11349 }
11350
11351 /* count the aggregation */
11352 if( aggregated )
11353 {
11354 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11355 (*naggrvars)++;
11356 success = TRUE;
11357 }
11358 }
11359
11360 if( success )
11361 {
11362 /* apply fixings and aggregation to successfully rerun this presolving step */
11363 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11364
11365 if( infeasible )
11366 {
11367 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11368 *cutoff = TRUE;
11369 return SCIP_OKAY;
11370 }
11371
11372 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11373
11374 if( infeasible )
11375 {
11376 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11377 *cutoff = TRUE;
11378 return SCIP_OKAY;
11379 }
11380 }
11381 }
11382 while( success && consdata->nvars >= 1 );
11383
11384 return SCIP_OKAY;
11385}
11386
11387
11388
11389/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11390 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11391 * coefficients
11392 */
11393static
11395{ /*lint --e{715}*/
11396 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11397 SCIP_VARTYPE vartype1;
11398 SCIP_VARTYPE vartype2;
11399 SCIP_Real value;
11400
11401 assert(consdata != NULL);
11402 assert(0 <= ind1 && ind1 < consdata->nvars);
11403 assert(0 <= ind2 && ind2 < consdata->nvars);
11404
11405 vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11406 vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11407
11408 if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11409 {
11410 /* continuous varibles will be sorted to the back */
11411 if( vartype2 != vartype1 )
11412 return +1;
11413 /* both variables are continuous */
11414 else
11415 return 0;
11416 }
11417 /* continuous variables will be sorted to the back */
11418 else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11419 return -1;
11420
11421 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11422
11423 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11424 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11425}
11426
11427/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11428 *
11429 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11430 * then we can change this constraint to 1^Tx = 1
11431 */
11432static
11434 SCIP* scip, /**< SCIP data structure */
11435 SCIP_CONS* cons, /**< linear constraint */
11436 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11437 int* nchgsides /**< pointer to store the amount of changed sides */
11438 )
11439{
11440 SCIP_CONSDATA* consdata;
11441 SCIP_VAR** vars;
11442 SCIP_Real* vals;
11443 SCIP_Real minval;
11444 SCIP_Real secondminval;
11445 SCIP_Real maxval;
11446 SCIP_Real lhs;
11447 SCIP_Real rhs;
11448 int nvars;
11449 int v;
11450
11451 /* we must not change a modifiable constraint in any way */
11452 if( SCIPconsIsModifiable(cons) )
11453 return SCIP_OKAY;
11454
11455 if( SCIPconsIsDeleted(cons) )
11456 return SCIP_OKAY;
11457
11458 consdata = SCIPconsGetData(cons);
11459 assert(consdata != NULL);
11460
11461 nvars = consdata->nvars;
11462
11463 /* do not check empty or bound-constraints */
11464 if( nvars < 2 )
11465 return SCIP_OKAY;
11466
11467 lhs = consdata->lhs;
11468 rhs = consdata->rhs;
11469 assert(!SCIPisInfinity(scip, -lhs));
11470 assert(!SCIPisInfinity(scip, rhs));
11471 assert(!SCIPisNegative(scip, rhs));
11472
11473 /* sides must be positive and different to detect set partition */
11474 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11475 return SCIP_OKAY;
11476
11477 vals = consdata->vals;
11478 vars = consdata->vars;
11479 assert(vars != NULL);
11480 assert(vals != NULL);
11481
11482 minval = SCIP_INVALID;
11483 secondminval = SCIP_INVALID;
11484 maxval = -SCIP_INVALID;
11485
11486 for( v = nvars - 1; v >= 0; --v )
11487 {
11488 if( SCIPvarIsBinary(vars[v]) )
11489 {
11490 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11491 {
11492 secondminval = minval;
11493 minval = vals[v];
11494 }
11495 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11496 secondminval = vals[v];
11497
11498 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11499 maxval = vals[v];
11500 }
11501 else
11502 break;
11503 }
11504
11505 /* check if all variables are binary, we can choose one, and need to choose at most one */
11506 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11507 && SCIPisGT(scip, minval + secondminval, rhs) )
11508 {
11509 /* change all coefficients to 1.0 */
11510 for( v = nvars - 1; v >= 0; --v )
11511 {
11512 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11513 }
11514 (*nchgcoefs) += nvars;
11515
11516 /* replace old right and left hand side with 1.0 */
11517 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11518 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11519 (*nchgsides) += 2;
11520 }
11521
11522 return SCIP_OKAY;
11523}
11524
11525/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11526 *
11527 * for both-sided constraints only @see rangedRowSimplify() will be called
11528 *
11529 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11530 *
11531 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11532 *
11533 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11534 *
11535 * 2. We try to remove redundant fractional parts in a constraint
11536 *
11537 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11538 *
11539 * 3. We are using the greatest common divisor for further reductions
11540 *
11541 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11542 * integral
11543 */
11544static
11546 SCIP* scip, /**< SCIP data structure */
11547 SCIP_CONS* cons, /**< linear constraint */
11548 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11549 int* nchgsides, /**< pointer to store the amount of changed sides */
11550 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11551 )
11552{
11553 SCIP_CONSDATA* consdata;
11554 SCIP_VAR** vars;
11555 SCIP_Real* vals;
11556 int* perm;
11557 SCIP_Real minactsub;
11558 SCIP_Real maxactsub;
11559 SCIP_Real siderest;
11560 SCIP_Real feastol;
11561 SCIP_Real newcoef;
11562 SCIP_Real absval;
11563 SCIP_Real minact;
11564 SCIP_Real maxact;
11565 SCIP_Real side;
11566 SCIP_Real lhs;
11567 SCIP_Real rhs;
11568 SCIP_Real lb;
11569 SCIP_Real ub;
11570 SCIP_Longint restcoef;
11571 SCIP_Longint oldgcd;
11572 SCIP_Longint rest;
11573 SCIP_Longint gcd;
11574 SCIP_Bool isminsettoinfinity;
11575 SCIP_Bool ismaxsettoinfinity;
11576 SCIP_Bool ismintight;
11577 SCIP_Bool ismaxtight;
11578 SCIP_Bool allcoefintegral;
11579 SCIP_Bool onlybin;
11580 SCIP_Bool hasrhs;
11581 SCIP_Bool haslhs;
11582 int oldnchgcoefs;
11583 int oldnchgsides;
11584 int foundbin;
11585 int candpos;
11586 int candpos2;
11587 int offsetv;
11588 int nvars;
11589 int v;
11590 int w;
11591
11592 assert(scip != NULL);
11593 assert(cons != NULL);
11594 assert(nchgcoefs != NULL);
11595 assert(nchgsides != NULL);
11596
11597 *infeasible = FALSE;
11598
11599 /* we must not change a modifiable constraint in any way */
11600 if( SCIPconsIsModifiable(cons) )
11601 return SCIP_OKAY;
11602
11603 if( SCIPconsIsDeleted(cons) )
11604 return SCIP_OKAY;
11605
11606 consdata = SCIPconsGetData(cons);
11607 assert(consdata != NULL);
11608
11609 nvars = consdata->nvars;
11610
11611 /* do not check empty or bound-constraints */
11612 if( nvars <= 2 )
11613 return SCIP_OKAY;
11614
11615 /* update maximal activity delta if necessary */
11616 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11618
11619 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11620 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11621 checkMaxActivityDelta(scip, consdata);
11622
11623 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11624 * accordingly
11625 */
11626 /* can only work with valid non-infinity activities per variable */
11627 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11628 return SCIP_OKAY;
11629
11630 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11631 * but the eventsystem seems to be full
11632 */
11633 consdata->normalized = FALSE;
11634
11635 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11636 assert(nvars == consdata->nvars);
11637
11638 if( *infeasible )
11639 return SCIP_OKAY;
11640
11641 if( !consdata->normalized )
11642 return SCIP_OKAY;
11643
11644 lhs = consdata->lhs;
11645 rhs = consdata->rhs;
11646 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11647 assert(!SCIPisNegative(scip, rhs));
11648
11649 if( !SCIPisInfinity(scip, -lhs) )
11650 haslhs = TRUE;
11651 else
11652 haslhs = FALSE;
11653
11654 if( !SCIPisInfinity(scip, rhs) )
11655 hasrhs = TRUE;
11656 else
11657 hasrhs = FALSE;
11658
11659 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11660 SCIPdebug( oldnchgsides = *nchgsides; )
11661
11662 /* @todo extend both-sided simplification */
11663 if( haslhs && hasrhs )
11664 {
11665 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11666
11667 return SCIP_OKAY;
11668 }
11669 assert(haslhs != hasrhs);
11670
11671 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11672 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11673 assert(!haslhs || !SCIPisNegative(scip, lhs));
11674
11675 /* get temporary memory to store the sorted permutation */
11677
11678 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11679 * value of their coefficients
11680 */
11681 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11682
11683 /* perform sorting after permutation array */
11684 permSortConsdata(consdata, perm, nvars);
11685 consdata->indexsorted = FALSE;
11686 consdata->coefsorted = FALSE;
11687
11688 vars = consdata->vars;
11689 vals = consdata->vals;
11690 assert(vars != NULL);
11691 assert(vals != NULL);
11692 assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11693
11694 /* free temporary memory */
11695 SCIPfreeBufferArray(scip, &perm);
11696
11697 /* only check constraints with at least two non continuous variables */
11699 return SCIP_OKAY;
11700
11701 /* do not process constraints when all coefficients are 1.0 */
11702 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11703 return SCIP_OKAY;
11704
11705 feastol = SCIPfeastol(scip);
11706
11707 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11709
11710 /* get global activities */
11711 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11712 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
11713
11714 /* cannot work with infinite activities */
11715 if( isminsettoinfinity || ismaxsettoinfinity )
11716 return SCIP_OKAY;
11717
11718 assert(ismintight);
11719 assert(ismaxtight);
11720 assert(maxact > minact);
11721 assert(!SCIPisInfinity(scip, -minact));
11722 assert(!SCIPisInfinity(scip, maxact));
11723
11724 v = 0;
11725 offsetv = -1;
11726 side = haslhs ? lhs : rhs;
11727 minactsub = minact;
11728 maxactsub = maxact;
11729
11730 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11731 * do not need to look at the large coefficients
11732 *
11733 * e.g. all x are binary, z are positive integer
11734 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11735 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11736 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11737 *
11738 * can be changed to
11739 *
11740 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11741 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11742 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11743 */
11744
11745 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11746 * hand side, we cannot apply the extra reduction step and need to reset v
11747 *
11748 * 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
11749 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11750 * for all i is a solution
11751 *
11752 * also redundancy of variables would not be correctly determined in such a case
11753 */
11754 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11755 {
11756 v = 1;
11757
11758 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11759 {
11760 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11761 * extra step, which might have worked
11762 */
11763 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11764 {
11765 v = 0;
11766 break;
11767 }
11768
11769 ++v;
11770 }
11771
11772 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11773 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11774 if( v == nvars )
11775 return SCIP_OKAY;
11776
11777 /* cannot work with continuous variables which have a big coefficient */
11778 if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11779 return SCIP_OKAY;
11780
11781 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11782 if( SCIPisEQ(scip, side, -vals[v]) )
11783 v = 0;
11784
11785 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11786 * reduction
11787 */
11788 if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11789 v = 0;
11790
11791 if( v > 0 )
11792 {
11793 assert(v < nvars);
11794
11795 offsetv = v - 1;
11796
11797 for( w = 0; w < v; ++w )
11798 {
11799 lb = SCIPvarGetLbGlobal(vars[w]);
11800 ub = SCIPvarGetUbGlobal(vars[w]);
11801
11802 assert(vals[w] > 0);
11803
11804 /* update residual activities */
11805 maxactsub -= ub * vals[w];
11806 minactsub -= lb * vals[w];
11807 assert(maxactsub > minactsub);
11808 }
11809 }
11810 }
11811
11812 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11813 *
11814 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11815 *
11816 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11817 * to
11818 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11819 */
11820 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11821 {
11822 SCIP_Bool redundant = FALSE;
11823 SCIP_Bool numericsok;
11824 SCIP_Bool rredundant;
11825 SCIP_Bool lredundant;
11826
11827 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11828 assert(gcd >= 1);
11829
11830 if( v == 0 )
11831 {
11832 lb = SCIPvarGetLbGlobal(vars[0]);
11833 ub = SCIPvarGetUbGlobal(vars[0]);
11834
11835 /* update residual activities */
11836 if( vals[0] > 0 )
11837 {
11838 maxactsub -= ub * vals[0];
11839 minactsub -= lb * vals[0];
11840 }
11841 else
11842 {
11843 maxactsub -= lb * vals[0];
11844 minactsub -= ub * vals[0];
11845 }
11846 assert(maxactsub > minactsub);
11847 ++v;
11848 }
11849
11850 siderest = -SCIP_INVALID;
11851 allcoefintegral = TRUE;
11852
11853 /* check if some variables always fit into the given constraint */
11854 for( ; v < nvars - 1; ++v )
11855 {
11857 break;
11858
11859 if( !SCIPisIntegral(scip, vals[v]) )
11860 {
11861 allcoefintegral = FALSE;
11862 break;
11863 }
11864
11865 /* calculate greatest common divisor for all general and binary variables */
11866 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11867
11868 if( gcd == 1 )
11869 break;
11870
11871 lb = SCIPvarGetLbGlobal(vars[v]);
11872 ub = SCIPvarGetUbGlobal(vars[v]);
11873
11874 assert(!SCIPisInfinity(scip, -lb));
11875 assert(!SCIPisInfinity(scip, ub));
11876
11877 /* update residual activities */
11878 if( vals[v] > 0 )
11879 {
11880 maxactsub -= ub * vals[v];
11881 minactsub -= lb * vals[v];
11882 }
11883 else
11884 {
11885 maxactsub -= lb * vals[v];
11886 minactsub -= ub * vals[v];
11887 }
11888 assert(SCIPisGE(scip, maxactsub, minactsub));
11889
11890 if( hasrhs )
11891 {
11892 /* determine the remainder of the right hand side and the gcd */
11893 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11894 }
11895 else
11896 {
11897 /* determine the remainder of the left hand side and the gcd */
11898 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11899 if( SCIPisZero(scip, siderest) )
11900 siderest = gcd;
11901 }
11902
11903 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11904 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11905
11906 /* early termination if the activities deceed the gcd */
11907 if( offsetv == -1 && (rredundant || lredundant) )
11908 {
11909 redundant = TRUE;
11910 break;
11911 }
11912 }
11913 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11914
11915 if( !redundant )
11916 {
11917 if( hasrhs )
11918 {
11919 /* determine the remainder of the right hand side and the gcd */
11920 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11921 }
11922 else
11923 {
11924 /* determine the remainder of the left hand side and the gcd */
11925 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11926 if( SCIPisZero(scip, siderest) )
11927 siderest = gcd;
11928 }
11929 }
11930 else
11931 ++v;
11932
11933 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",
11934 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11935
11936 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11937 * reasonable absolute values */
11938 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11939 REALABS(minactsub) < MAXACTVAL;
11940
11941 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11942 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11943
11944 /* check if we can remove redundant variables */
11945 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11946 {
11947 SCIP_Real oldcoef;
11948
11949 /* double check the redundancy */
11950#ifndef NDEBUG
11951 SCIP_Real tmpminactsub = 0.0;
11952 SCIP_Real tmpmaxactsub = 0.0;
11953
11954 /* recompute residual activities */
11955 for( w = v; w < nvars; ++w )
11956 {
11957 lb = SCIPvarGetLbGlobal(vars[w]);
11958 ub = SCIPvarGetUbGlobal(vars[w]);
11959
11960 assert(!SCIPisInfinity(scip, -lb));
11961 assert(!SCIPisInfinity(scip, ub));
11962
11963 /* update residual activities */
11964 if( vals[w] > 0 )
11965 {
11966 tmpmaxactsub += ub * vals[w];
11967 tmpminactsub += lb * vals[w];
11968 }
11969 else
11970 {
11971 tmpmaxactsub += lb * vals[w];
11972 tmpminactsub += ub * vals[w];
11973 }
11974 assert(tmpmaxactsub >= tmpminactsub);
11975 }
11976
11977 if( hasrhs )
11978 {
11979 assert(offsetv == -1);
11980
11981 /* determine the remainder of the right hand side and the gcd */
11982 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11983 }
11984 else
11985 {
11986 /* determine the remainder of the left hand side and the gcd */
11987 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11988 if( SCIPisZero(scip, siderest) )
11989 siderest = gcd;
11990 }
11991
11992 /* is the redundancy really fulfilled */
11993 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11994 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11995#endif
11996
11997 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11998 nvars - v, SCIPconsGetName(cons));
11999
12000 /* remove redundant variables */
12001 for( w = nvars - 1; w >= v; --w )
12002 {
12003 SCIP_CALL( delCoefPos(scip, cons, w) );
12004 }
12005 (*nchgcoefs) += (nvars - v);
12006
12007 assert(w >= 0);
12008
12009 oldcoef = vals[w];
12010
12011 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12012 assert(vars == consdata->vars);
12013 assert(vals == consdata->vals);
12015
12016 if( *infeasible )
12017 return SCIP_OKAY;
12018
12019 /* compute new greatest common divisor due to normalization */
12020 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
12021 assert(gcd >= 1);
12022
12023 /* update side */
12024 if( hasrhs )
12025 {
12026 /* replace old with new right hand side */
12027 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
12028 rhs = consdata->rhs;
12029 }
12030 else
12031 {
12032 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
12033 {
12034 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
12035 lhs = consdata->lhs;
12036 }
12037 else
12038 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
12039 }
12040 ++(*nchgsides);
12041
12042 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12043 assert(!haslhs || !SCIPisNegative(scip, lhs));
12044
12045 /* get new constraint data */
12046 nvars = consdata->nvars;
12047 assert(nvars > 0);
12048
12049 allcoefintegral = TRUE;
12050
12051#ifndef NDEBUG
12052 /* check integrality */
12053 for( w = offsetv + 1; w < nvars; ++w )
12054 {
12055 assert(SCIPisIntegral(scip, vals[w]));
12056 }
12057#endif
12059 }
12060
12061 /* try to find a better gcd, when having large coefficients */
12062 if( offsetv >= 0 && gcd == 1 )
12063 {
12064 /* calculate greatest common divisor for all general variables */
12065 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
12066
12067 if( gcd > 1 )
12068 {
12069 gcd = -1;
12070 candpos = -1;
12071
12072 for( v = nvars - 1; v > offsetv; --v )
12073 {
12074 assert(!SCIPisZero(scip, vals[v]));
12076 break;
12077
12078 if( !SCIPisIntegral(scip, vals[v]) )
12079 {
12080 allcoefintegral = FALSE;
12081 break;
12082 }
12083
12084 oldgcd = gcd;
12085
12086 if( gcd == -1 )
12087 {
12088 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12089 assert(gcd >= 1);
12090 }
12091 else
12092 {
12093 /* calculate greatest common divisor for all general and binary variables */
12094 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12095 }
12096
12097 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12098 * can stop searching
12099 */
12100 if( gcd == 1 )
12101 {
12102 if( !SCIPvarIsBinary(vars[v]) )
12103 break;
12104
12105 /* found candidate */
12106 if( candpos == -1 )
12107 {
12108 gcd = oldgcd;
12109 candpos = v;
12110 }
12111 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12112 else
12113 break;
12114 }
12115 }
12116 assert(v > offsetv || candpos > offsetv);
12117 }
12118 else
12119 candpos = -1;
12120 }
12121 else
12122 candpos = nvars - 1;
12123
12124 /* check last coefficient for integrality */
12125 if( gcd > 1 && allcoefintegral && !redundant )
12126 {
12127 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12128 allcoefintegral = FALSE;
12129 }
12130
12131 /* check for further necessary coefficient adjustments */
12132 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12133 {
12134 assert(offsetv + 1 < nvars);
12135 assert(0 <= candpos && candpos < nvars);
12136
12138 {
12139 SCIP_Bool notchangable = FALSE;
12140
12141#ifndef NDEBUG
12142 /* check integrality */
12143 for( w = offsetv + 1; w < nvars; ++w )
12144 {
12145 assert(SCIPisIntegral(scip, vals[w]));
12146 }
12147#endif
12148
12149 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12150 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12151 {
12152 /* determine the remainder of the side and the gcd */
12153 if( hasrhs )
12154 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12155 else
12156 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12157 assert(rest >= 0);
12158 assert(rest < gcd);
12159
12160 /* determine the remainder of the coefficient candidate and the gcd */
12161 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12162 assert(restcoef >= 1);
12163 assert(restcoef < gcd);
12164
12165 if( hasrhs )
12166 {
12167 /* calculate new coefficient */
12168 if( restcoef > rest )
12169 newcoef = vals[candpos] - restcoef + gcd;
12170 else
12171 newcoef = vals[candpos] - restcoef;
12172 }
12173 else
12174 {
12175 /* calculate new coefficient */
12176 if( rest == 0 || restcoef < rest )
12177 newcoef = vals[candpos] - restcoef;
12178 else
12179 newcoef = vals[candpos] - restcoef + gcd;
12180 }
12181
12182 /* done */
12183
12184 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12185 * another with the big coefficient was set to 1
12186 */
12187 if( hasrhs && SCIPisZero(scip, newcoef) )
12188 {
12189 notchangable = TRUE;
12190 }
12191 else if( SCIPisZero(scip, newcoef) )
12192 {
12193 /* delete old redundant coefficient */
12194 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12195 ++(*nchgcoefs);
12196 }
12197 else
12198 {
12199 /* replace old with new coefficient */
12200 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12201 ++(*nchgcoefs);
12202 }
12203 }
12204 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12205 {
12206 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12207 }
12208
12209 /* correct side and big coefficients */
12210 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12211 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12212 {
12213 if( haslhs )
12214 {
12215 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12216
12217 SCIP_CALL( chgLhs(scip, cons, newcoef) );
12218 ++(*nchgsides);
12219 }
12220 else
12221 {
12222 assert(hasrhs);
12223 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12224
12225 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12226 ++(*nchgsides);
12227 }
12228
12229 /* correct coefficients up front */
12230 for( w = offsetv; w >= 0; --w )
12231 {
12232 assert(vals[w] > 0);
12233
12234 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12235 }
12236 (*nchgcoefs) += (offsetv + 1);
12237 }
12238
12239 if( !notchangable )
12240 {
12241 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12242 assert(vars == consdata->vars);
12243 assert(vals == consdata->vals);
12244
12245 if( *infeasible )
12246 return SCIP_OKAY;
12247
12248 /* get new constraint data */
12249 nvars = consdata->nvars;
12250 assert(nvars >= 2);
12251
12253
12254 lhs = consdata->lhs;
12255 rhs = consdata->rhs;
12256 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12257 assert(!haslhs || !SCIPisNegative(scip, lhs));
12258 }
12259 }
12260 }
12261 }
12262
12263 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12264 /* no continuous variables are left over */
12266 return SCIP_OKAY;
12267
12268 onlybin = TRUE;
12269 allcoefintegral = TRUE;
12270 /* check if all variables are of binary type */
12271 for( v = nvars - 1; v >= 0; --v )
12272 {
12273 if( !SCIPvarIsBinary(vars[v]) )
12274 onlybin = FALSE;
12275 if( !SCIPisIntegral(scip, vals[v]) )
12276 allcoefintegral = FALSE;
12277 }
12278
12279 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12280 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12281 *
12282 * @todo there are some steps missing ....
12283 */
12284 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12285 {
12286 SCIP_Real val;
12287 SCIP_Real newval;
12288 SCIP_Real frac = 0.0;
12289 SCIP_Bool found = FALSE;
12290
12291 if( hasrhs )
12292 {
12293 if( allcoefintegral )
12294 {
12295 /* replace old with new right hand side */
12296 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12297 ++(*nchgsides);
12298 }
12299 else
12300 {
12301 siderest = rhs - SCIPfloor(scip, rhs);
12302
12303 /* try to round down all non-integral coefficients */
12304 for( v = nvars - 1; v >= 0; --v )
12305 {
12306 val = vals[v];
12307
12308 /* add up all possible fractional parts */
12309 if( !SCIPisIntegral(scip, val) )
12310 {
12311 lb = SCIPvarGetLbGlobal(vars[v]);
12312 ub = SCIPvarGetUbGlobal(vars[v]);
12313
12314 /* at least one bound need to be at zero */
12315 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12316 return SCIP_OKAY;
12317
12318 /* swap bounds for 'standard' form */
12319 if( !SCIPisFeasZero(scip, lb) )
12320 {
12321 ub = lb;
12322 val *= -1;
12323 }
12324
12325 found = TRUE;
12326
12327 frac += (val - SCIPfloor(scip, val)) * ub;
12328
12329 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12330 *
12331 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12332 * x3, x4 set to 1 would be infeasible but feasible after flooring
12333 */
12334 if( SCIPisGT(scip, frac, siderest) )
12335 return SCIP_OKAY;
12336 }
12337 }
12338 assert(v == -1);
12339
12340 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12341
12342 /* round rhs and coefficients to integral values */
12343 if( found )
12344 {
12345 for( v = nvars - 1; v >= 0; --v )
12346 {
12347 val = vals[v];
12348
12349 /* add the whole fractional part */
12350 if( !SCIPisIntegral(scip, val) )
12351 {
12352 lb = SCIPvarGetLbGlobal(vars[v]);
12353
12354 if( SCIPisFeasZero(scip, lb) )
12355 newval = SCIPfloor(scip, val);
12356 else
12357 newval = SCIPceil(scip, val);
12358
12359 if( SCIPisZero(scip, newval) )
12360 {
12361 /* delete old redundant coefficient */
12362 SCIP_CALL( delCoefPos(scip, cons, v) );
12363 ++(*nchgcoefs);
12364 }
12365 else
12366 {
12367 /* replace old with new coefficient */
12368 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12369 ++(*nchgcoefs);
12370 }
12371 }
12372 }
12373 }
12374
12375 /* replace old with new right hand side */
12376 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12377 ++(*nchgsides);
12378 }
12379 }
12380 else
12381 {
12382 if( allcoefintegral )
12383 {
12384 /* replace old with new left hand side */
12385 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12386 ++(*nchgsides);
12387 }
12388 else
12389 {
12390 /* cannot floor left hand side to zero */
12391 if( SCIPisLT(scip, lhs, 1.0) )
12392 return SCIP_OKAY;
12393
12394 siderest = lhs - SCIPfloor(scip, lhs);
12395
12396 /* try to round down all non-integral coefficients */
12397 for( v = nvars - 1; v >= 0; --v )
12398 {
12399 val = vals[v];
12400
12401 /* add up all possible fractional parts */
12402 if( !SCIPisIntegral(scip, val) )
12403 {
12404 lb = SCIPvarGetLbGlobal(vars[v]);
12405 ub = SCIPvarGetUbGlobal(vars[v]);
12406
12407 /* at least one bound need to be at zero */
12408 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12409 return SCIP_OKAY;
12410
12411 /* swap bounds for 'standard' form */
12412 if( !SCIPisFeasZero(scip, lb) )
12413 {
12414 ub = lb;
12415 val *= -1;
12416 }
12417
12418 /* cannot floor to zero */
12419 if( SCIPisLT(scip, val, 1.0) )
12420 return SCIP_OKAY;
12421
12422 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12423 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12424 return SCIP_OKAY;
12425
12426 found = TRUE;
12427
12428 frac += (val - SCIPfloor(scip, val)) * ub;
12429
12430 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12431 * fractional parts of the variables, we cannot tighten the coefficients
12432 *
12433 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12434 * x2-x4 set to 1 would be feasible but not after flooring
12435 */
12436 if( SCIPisGE(scip, frac, 1 + siderest) )
12437 return SCIP_OKAY;
12438 }
12439 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12440 else
12441 return SCIP_OKAY;
12442 }
12443 assert(v == -1);
12444
12445 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12446
12447 /* round lhs and coefficients to integral values */
12448 if( found )
12449 {
12450 for( v = nvars - 1; v >= 0; --v )
12451 {
12452 val = vals[v];
12453
12454 /* add the whole fractional part */
12455 if( !SCIPisIntegral(scip, val) )
12456 {
12457 lb = SCIPvarGetLbGlobal(vars[v]);
12458
12459 if( SCIPisFeasZero(scip, lb) )
12460 newval = SCIPfloor(scip, val);
12461 else
12462 newval = SCIPceil(scip, val);
12463
12464 if( SCIPisZero(scip, newval) )
12465 {
12466 /* delete old redundant coefficient */
12467 SCIP_CALL( delCoefPos(scip, cons, v) );
12468 ++(*nchgcoefs);
12469 }
12470 else
12471 {
12472 /* replace old with new coefficient */
12473 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12474 ++(*nchgcoefs);
12475 }
12476 }
12477 }
12478 }
12479
12480 /* replace old with new left hand side */
12481 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12482 ++(*nchgsides);
12483 }
12484 }
12485
12486 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12487 assert(vars == consdata->vars);
12488 assert(vals == consdata->vals);
12489
12490 if( *infeasible )
12491 return SCIP_OKAY;
12492
12493 rhs = consdata->rhs;
12494 lhs = consdata->lhs;
12495
12496 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12497 assert(!haslhs || !SCIPisNegative(scip, lhs));
12498
12500
12501 nvars = consdata->nvars;
12502 if( nvars < 2 )
12503 return SCIP_OKAY;
12504
12505 allcoefintegral = TRUE;
12506#ifndef NDEBUG
12507 /* debug check if all coefficients are really integral */
12508 for( v = nvars - 1; v >= 0; --v )
12509 assert(SCIPisIntegral(scip, vals[v]));
12510#endif
12511 }
12512
12513 /* @todo following can also work on non integral coefficients, need more investigation */
12514 /* only check constraints with integral coefficients on all integral variables */
12515 if( !allcoefintegral )
12516 return SCIP_OKAY;
12517
12518 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12519 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12520 return SCIP_OKAY;
12521
12522 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12523 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12524 return SCIP_OKAY;
12525
12526 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12527 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12528 return SCIP_OKAY;
12529
12530 assert(nvars >= 2);
12531
12532 /* start gcd procedure for all variables */
12533 do
12534 {
12535 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12536 SCIPdebug( oldnchgsides = *nchgsides; )
12537
12538 /* stop if we have two coeffcients which are one in absolute value */
12539 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12540 return SCIP_OKAY;
12541
12542 gcd = -1;
12543
12544 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12545 * because coefficients of non-binary variables might have changed to zero */
12546 if( !onlybin )
12547 {
12548 foundbin = -1;
12549 onlybin = TRUE;
12550
12551 for( v = nvars - 1; v >= 0; --v )
12552 {
12553 assert(!SCIPisZero(scip, vals[v]));
12555
12556 if( SCIPvarIsBinary(vars[v]) )
12557 {
12558 if( foundbin == -1 )
12559 foundbin = v;
12560 continue;
12561 }
12562 else
12563 onlybin = FALSE;
12564
12565 absval = REALABS(vals[v]);
12566 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12567 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12568 */
12569 assert(SCIPisFeasIntegral(scip, absval));
12570
12571 if( gcd == -1 )
12572 {
12573 gcd = (SCIP_Longint)(absval + feastol);
12574 assert(gcd >= 1);
12575 }
12576 else
12577 {
12578 /* calculate greatest common divisor for all general variables */
12579 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12580 }
12581 if( gcd == 1 )
12582 break;
12583 }
12584 }
12585 else
12586 foundbin = nvars - 1;
12587
12588 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12589 if( gcd == 1 || foundbin == -1)
12590 return SCIP_OKAY;
12591
12592 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12593
12594 candpos = -1;
12595 candpos2 = -1;
12596
12597 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12598 * change the coefficient
12599 */
12600 for( v = foundbin; v >= 0; --v )
12601 {
12602 if( onlybin || SCIPvarIsBinary(vars[v]) )
12603 {
12604 absval = REALABS(vals[v]);
12605 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12606 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12607 */
12608 assert(SCIPisFeasIntegral(scip, absval));
12609
12610 oldgcd = gcd;
12611
12612 if( gcd == -1 )
12613 {
12614 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12615 assert(gcd >= 1);
12616 }
12617 else
12618 {
12619 /* calculate greatest common divisor for all general and binary variables */
12620 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12621 }
12622
12623 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12624 * can terminate
12625 */
12626 if( gcd == 1 )
12627 {
12628 /* found candidate */
12629 if( candpos == -1 )
12630 {
12631 gcd = oldgcd;
12632 candpos = v;
12633
12634 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12635 * the coefficient change
12636 */
12637 if( onlybin && v == foundbin - 1 )
12638 candpos2 = foundbin;
12639 }
12640 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12641 else
12642 {
12643 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12644 {
12645 assert(candpos2 == nvars - 1);
12646
12647 /* take new candidates */
12648 candpos = candpos2;
12649
12650 /* recalculate gcd from scratch */
12651 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12652 assert(gcd >= 1);
12653
12654 /* calculate greatest common divisor for all general and binary variables */
12655 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12656 if( gcd == 1 )
12657 return SCIP_OKAY;
12658 }
12659 else
12660 /* cannot determine a possible coefficient for reduction */
12661 return SCIP_OKAY;
12662 }
12663 }
12664 }
12665 }
12666 assert(gcd >= 2);
12667
12668 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12669 * further
12670 */
12671 assert(candpos >= 0 && candpos < nvars);
12672
12673 /* all variables and all coefficients are integral, so the side should be too */
12674 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12675
12676 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12677 * @see normalizeCons()
12678 */
12679 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12680 assert(!haslhs || !SCIPisNegative(scip, lhs));
12681
12682 /* determine the remainder of the side and the gcd */
12683 if( hasrhs )
12684 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12685 else
12686 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12687 assert(rest >= 0);
12688 assert(rest < gcd);
12689
12690 /* determine the remainder of the coefficient candidate and the gcd */
12691 if( vals[candpos] < 0 )
12692 {
12693 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12694 assert(restcoef <= -1);
12695 restcoef += gcd;
12696 }
12697 else
12698 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12699 assert(restcoef >= 1);
12700 assert(restcoef < gcd);
12701
12702 if( hasrhs )
12703 {
12704 if( rest > 0 )
12705 {
12706 /* replace old with new right hand side */
12707 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12708 ++(*nchgsides);
12709 }
12710
12711 /* calculate new coefficient */
12712 if( restcoef > rest )
12713 newcoef = vals[candpos] - restcoef + gcd;
12714 else
12715 newcoef = vals[candpos] - restcoef;
12716 }
12717 else
12718 {
12719 if( rest > 0 )
12720 {
12721 /* replace old with new left hand side */
12722 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12723 ++(*nchgsides);
12724 }
12725
12726 /* calculate new coefficient */
12727 if( rest == 0 || restcoef < rest )
12728 newcoef = vals[candpos] - restcoef;
12729 else
12730 newcoef = vals[candpos] - restcoef + gcd;
12731 }
12732 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12733
12734 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));
12735
12736 if( SCIPisZero(scip, newcoef) )
12737 {
12738 /* delete redundant coefficient */
12739 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12740 }
12741 else
12742 {
12743 /* replace old with new coefficient */
12744 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12745 }
12746 ++(*nchgcoefs);
12747
12748 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12749 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12750 assert(vars == consdata->vars);
12751 assert(vals == consdata->vals);
12752
12753 if( *infeasible )
12754 return SCIP_OKAY;
12755
12757
12758 rhs = consdata->rhs;
12759 lhs = consdata->lhs;
12760 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12761 assert(!haslhs || !SCIPisNegative(scip, lhs));
12762
12763 nvars = consdata->nvars;
12764
12765 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));
12766 }
12767 while( nvars >= 2 );
12768
12769 return SCIP_OKAY;
12770}
12771
12772
12773/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12774 * cons0 := a * cons0 + b * cons1,
12775 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12776 * for numerical stability, we will only accept integral a and b;
12777 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12778 * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12779 */
12780static
12782 SCIP* scip, /**< SCIP data structure */
12783 SCIP_CONS* cons0, /**< (in)equality to modify */
12784 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12785 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12786 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12787 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12788 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12789 int nvarscommon, /**< number of variables, that appear in both constraints */
12790 int commonidxweight, /**< variable weight sum of common variables */
12791 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12792 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12793 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12794 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12795 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12796 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12797 )
12798{
12799 SCIP_CONSDATA* consdata0;
12800 SCIP_CONSDATA* consdata1;
12801 SCIP_Real a;
12802 SCIP_Real b;
12803 SCIP_Real aggrcoef;
12804 SCIP_Real scalarsum;
12805 SCIP_Real bestscalarsum;
12806 SCIP_Bool betterscalarsum;
12807 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12808 int varweight;
12809 int nvars;
12810 int bestvarweight;
12811 int bestnvars;
12812 int bestv;
12813 int v;
12814 int i;
12815
12816 assert(scip != NULL);
12817 assert(cons0 != NULL);
12818 assert(cons1 != NULL);
12819 assert(commonidx0 != NULL);
12820 assert(commonidx1 != NULL);
12821 assert(diffidx0minus1 != NULL);
12822 assert(diffidx1minus0 != NULL);
12823 assert(nvarscommon >= 1);
12824 assert(commonidxweight >= nvarscommon);
12825 assert(nchgcoefs != NULL);
12826 assert(aggregated != NULL);
12827
12828 assert(SCIPconsIsActive(cons0));
12829 assert(SCIPconsIsActive(cons1));
12830
12831 *infeasible = FALSE;
12832
12833 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12834
12835 /* cons0 is an (in)equality */
12836 consdata0 = SCIPconsGetData(cons0);
12837 assert(consdata0 != NULL);
12838 assert(consdata0->nvars >= 1);
12839 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12840 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12841
12842 /* cons1 is an equality */
12843 consdata1 = SCIPconsGetData(cons1);
12844 assert(consdata1 != NULL);
12845 assert(consdata1->nvars >= 1);
12846 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12847 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12848
12849 *aggregated = FALSE;
12850
12851 /* search for the best common variable such that
12852 * val1[var] * consdata0 - val0[var] * consdata1
12853 * has least weighted number of variables
12854 */
12855 bestvarweight = commonidxweight + diffidx0minus1weight;
12856 bestnvars = consdata0->nvars;
12857 bestv = -1;
12858 bestscalarsum = 0.0;
12859 commonvarlindependent = TRUE;
12860 for( v = 0; v < nvarscommon; ++v )
12861 {
12862 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12863 a = consdata1->vals[commonidx1[v]];
12864 b = -consdata0->vals[commonidx0[v]];
12865
12866 /* only try aggregation, if coefficients are integral (numerical stability) */
12868 {
12869 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12870 varweight = diffidx0minus1weight + diffidx1minus0weight;
12871 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12872 scalarsum = REALABS(a) + REALABS(b);
12873 betterscalarsum = (scalarsum < bestscalarsum);
12874 for( i = 0; i < nvarscommon
12875 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12876 {
12877 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12878 if( !SCIPisZero(scip, aggrcoef) )
12879 {
12880 varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12881 nvars++;
12882 }
12883 }
12884 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12885 {
12886 bestv = v;
12887 bestvarweight = varweight;
12888 bestnvars = nvars;
12889 bestscalarsum = scalarsum;
12890 }
12891 }
12892
12893 /* update commonvarlindependent flag, if still TRUE:
12894 * 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
12895 */
12896 if( commonvarlindependent && v > 0 )
12897 commonvarlindependent = SCIPisEQ(scip,
12898 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12899 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12900 }
12901
12902 /* if better aggregation was found, create new constraint and delete old one */
12903 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12904 {
12905 SCIP_CONS* newcons;
12906 SCIP_CONSDATA* newconsdata;
12907 SCIP_VAR** newvars;
12908 SCIP_Real* newvals;
12909 SCIP_Real newlhs;
12910 SCIP_Real newrhs;
12911 int newnvars;
12912
12913 if( bestv != -1 )
12914 {
12915 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12916 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12917 {
12918 a = consdata1->vals[commonidx1[bestv]];
12919 b = -consdata0->vals[commonidx0[bestv]];
12920 }
12921 else
12922 {
12923 a = -consdata1->vals[commonidx1[bestv]];
12924 b = consdata0->vals[commonidx0[bestv]];
12925 }
12929 assert(!SCIPisZero(scip, b));
12930 }
12931 else
12932 {
12933 assert(commonvarlindependent);
12934 if( consdata1->vals[commonidx1[0]] > 0.0 )
12935 {
12936 a = consdata1->vals[commonidx1[0]];
12937 b = -consdata0->vals[commonidx0[0]];
12938 }
12939 else
12940 {
12941 a = -consdata1->vals[commonidx1[0]];
12942 b = consdata0->vals[commonidx0[0]];
12943 }
12945 assert(!SCIPisZero(scip, b));
12946
12947 /* if a/b is integral, then we can easily choose integer multipliers */
12948 if( SCIPisIntegral(scip, a/b) )
12949 {
12950 if( a/b > 0 )
12951 {
12952 a /= b;
12953 b = 1.0;
12954 }
12955 else
12956 {
12957 a /= -b;
12958 b = -1.0;
12959 }
12960 }
12961
12962 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12963 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12964 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12965 }
12966
12967 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12968 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12969 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12970 SCIPdebugPrintCons(scip, cons0, NULL);
12971 SCIPdebugPrintCons(scip, cons1, NULL);
12972
12973 /* get temporary memory for creating the new linear constraint */
12974 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12975 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12976
12977 /* calculate the common coefficients, if we have not recognized linear dependency */
12978 newnvars = 0;
12979 if( !commonvarlindependent )
12980 {
12981 for( i = 0; i < nvarscommon; ++i )
12982 {
12983 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12984 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12985
12986 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12987 if( !SCIPisZero(scip, aggrcoef) )
12988 {
12989 assert(newnvars < bestnvars);
12990 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12991 newvals[newnvars] = aggrcoef;
12992 newnvars++;
12993 }
12994 }
12995 }
12996 else
12997 {
12998 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12999#ifndef NDEBUG
13000 for( i = 0; i < nvarscommon; ++i )
13001 {
13002 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
13003 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
13004
13005 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
13006 assert(SCIPisZero(scip, aggrcoef));
13007 }
13008#endif
13009 }
13010
13011 /* calculate the coefficients appearing in cons0 but not in cons1 */
13012 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
13013 {
13014 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
13015
13016 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
13017 assert(!SCIPisZero(scip, aggrcoef));
13018 assert(newnvars < bestnvars);
13019 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
13020 newvals[newnvars] = aggrcoef;
13021 newnvars++;
13022 }
13023
13024 /* calculate the coefficients appearing in cons1 but not in cons0 */
13025 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
13026 {
13027 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
13028
13029 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
13030 assert(!SCIPisZero(scip, aggrcoef));
13031 assert(newnvars < bestnvars);
13032 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
13033 newvals[newnvars] = aggrcoef;
13034 newnvars++;
13035 }
13036 assert(newnvars == bestnvars);
13037
13038 /* calculate the new left and right hand side of the (in)equality */
13039 assert(!SCIPisInfinity(scip, -consdata1->lhs));
13040 assert(!SCIPisInfinity(scip, consdata1->rhs));
13041 if( SCIPisInfinity(scip, -consdata0->lhs) )
13042 newlhs = -SCIPinfinity(scip);
13043 else
13044 newlhs = a * consdata0->lhs + b * consdata1->lhs;
13045 if( SCIPisInfinity(scip, consdata0->rhs) )
13046 newrhs = SCIPinfinity(scip);
13047 else
13048 newrhs = a * consdata0->rhs + b * consdata1->rhs;
13049
13050 /* create the new linear constraint */
13051 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
13056
13057 newconsdata = SCIPconsGetData(newcons);
13058 assert(newconsdata != NULL);
13059
13060 /* copy the upgraded flag from the old cons0 to the new constraint */
13061 newconsdata->upgraded = consdata0->upgraded;
13062
13063 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
13064
13065 if( *infeasible )
13066 goto TERMINATE;
13067
13068 /* check, if we really want to use the new constraint instead of the old one:
13069 * use the new one, if the maximum norm doesn't grow too much
13070 */
13071 if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
13072 {
13073 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
13074 SCIPdebugPrintCons(scip, newcons, NULL);
13075
13076 /* update the statistics: we changed all coefficients */
13077 if( !consdata0->upgraded )
13078 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
13079 *aggregated = TRUE;
13080
13081 /* delete the old constraint, and add the new linear constraint to the problem */
13082 SCIP_CALL( SCIPdelCons(scip, cons0) );
13083 SCIP_CALL( SCIPaddCons(scip, newcons) );
13084 }
13085
13086 TERMINATE:
13087 /* release the new constraint */
13088 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
13089
13090 /* free temporary memory */
13091 SCIPfreeBufferArray(scip, &newvals);
13092 SCIPfreeBufferArray(scip, &newvars);
13093 }
13094
13095 return SCIP_OKAY;
13096}
13097
13098/** gets the key of the given element */
13099static
13100SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
13101{ /*lint --e{715}*/
13102 /* the key is the element itself */
13103 return elem;
13104}
13105
13106/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13107 * coefficients are either equal or negated
13108 */
13109static
13110SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
13111{
13112 SCIP* scip;
13113 SCIP_CONSDATA* consdata1;
13114 SCIP_CONSDATA* consdata2;
13115 SCIP_Real cons1scale;
13116 SCIP_Real cons2scale;
13117 int i;
13118
13119 assert(key1 != NULL);
13120 assert(key2 != NULL);
13121 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13122 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13123 assert(consdata1->indexsorted);
13124 assert(consdata2->indexsorted);
13125
13126 scip = (SCIP*)userptr;
13127 assert(scip != NULL);
13128
13129 /* if it is the same constraint we dont need to check anything */
13130 if( key1 == key2 )
13131 return TRUE;
13132
13133 /* checks trivial case */
13134 if( consdata1->nvars != consdata2->nvars )
13135 return FALSE;
13136
13137 /* tests if variables are equal */
13138 for( i = 0; i < consdata1->nvars; ++i )
13139 {
13140 if( consdata1->vars[i] != consdata2->vars[i] )
13141 {
13142 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13143 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13144 return FALSE;
13145 }
13146 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13147 }
13148
13149 /* compute scale before comparing coefficients of constraints */
13150 cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
13151 cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
13152
13153 /* tests if coefficients are equal with the computed scale */
13154 for( i = 0; i < consdata1->nvars; ++i )
13155 {
13156 SCIP_Real val1;
13157 SCIP_Real val2;
13158
13159 val1 = consdata1->vals[i] * cons1scale;
13160 val2 = consdata2->vals[i] * cons2scale;
13161
13162 if( !SCIPisEQ(scip, val1, val2) )
13163 return FALSE;
13164 }
13165
13166 return TRUE;
13167}
13168
13169/** returns the hash value of the key */
13170static
13171SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13172{
13173 SCIP_CONSDATA* consdata;
13174 int minidx;
13175 int mididx;
13176 int maxidx;
13177 SCIP_Real scale;
13178#ifndef NDEBUG
13179 SCIP* scip;
13180
13181 scip = (SCIP*)userptr;
13182 assert(scip != NULL);
13183#endif
13184
13185 assert(key != NULL);
13186 consdata = SCIPconsGetData((SCIP_CONS*)key);
13187 assert(consdata != NULL);
13188 assert(consdata->nvars > 0);
13189
13190 assert(consdata->indexsorted);
13191
13192 minidx = SCIPvarGetIndex(consdata->vars[0]);
13193 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13194 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13195 scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
13196
13197 /* using only the variable indices as hash, since the values are compared by epsilon */
13198 return SCIPhashSeven(consdata->nvars, minidx, SCIPrealHashCode(consdata->vals[0] * scale),
13199 mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale),
13200 maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale));
13201}
13202
13203/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13204 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13205 */
13206static
13208 SCIP_CONS* cons /**< linear constraint */
13209 )
13210{
13211 SCIP_CONSDATA* consdata;
13212
13213 assert(cons != NULL);
13214
13215 consdata = SCIPconsGetData(cons);
13216 assert(consdata != NULL);
13217
13218 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13219}
13220
13221/** updates the hashtable such that out of all constraints in the hashtable that are detected
13222 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13223 * and all others are removed from the hashtable and stored in the given array
13224 */
13225static
13227 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13228 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13229 * upon return will contain the constraint that should be kept */
13230 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13231 * these constraints where removed from the hashtable */
13232 int* nparallelconss /**< pointer to return number of parallel constraints */
13233 )
13234{
13235 SCIP_CONS* parallelcons;
13236 unsigned int querykey;
13237
13238 *nparallelconss = 0;
13239 querykey = getParallelConsKey(*querycons);
13240
13241 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13242 {
13243 unsigned int conskey = getParallelConsKey(parallelcons);
13244
13245 if( conskey < querykey )
13246 {
13247 parallelconss[(*nparallelconss)++] = *querycons;
13248 *querycons = parallelcons;
13249 querykey = conskey;
13250 }
13251 else
13252 {
13253 parallelconss[(*nparallelconss)++] = parallelcons;
13254 }
13255
13256 /* if the constraint that just came out of the hash table is the one that is kept,
13257 * we do not need to look into the hashtable again, since the invariant is that
13258 * in the hashtable only pair-wise non-parallel constraints are contained.
13259 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13260 * could be contained due to non-transitivity of the equality comparison.
13261 * Also we can return immediately, since parallelcons is already contained in the
13262 * hashtable and we do not need to remove and reinsert it.
13263 */
13264 if( *querycons == parallelcons )
13265 return SCIP_OKAY;
13266
13267 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13268 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13269 }
13270
13271 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13272 * comnpares equal to querycons at this point
13273 */
13274#ifndef NDEBUG
13275 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13276#else
13277 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13278#endif
13279
13280 return SCIP_OKAY;
13281}
13282
13283/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13284 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13285 */
13286static
13288 SCIP* scip, /**< SCIP data structure */
13289 BMS_BLKMEM* blkmem, /**< block memory */
13290 SCIP_CONS** conss, /**< constraint set */
13291 int nconss, /**< number of constraints in constraint set */
13292 int* firstchange, /**< pointer to store first changed constraint */
13293 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13294 int* ndelconss, /**< pointer to count number of deleted constraints */
13295 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13296 )
13297{
13298 SCIP_HASHTABLE* hashtable;
13299 SCIP_CONS** parallelconss;
13300 int nparallelconss;
13301 int hashtablesize;
13302 int c;
13303
13304 assert(scip != NULL);
13305 assert(blkmem != NULL);
13306 assert(conss != NULL);
13307 assert(firstchange != NULL);
13308 assert(cutoff != NULL);
13309 assert(ndelconss != NULL);
13310 assert(nchgsides != NULL);
13311
13312 /* create a hash table for the constraint set */
13313 hashtablesize = nconss;
13314 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13315 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13316
13317 SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13318
13319 /* check all constraints in the given set for redundancy */
13320 for( c = 0; c < nconss; ++c )
13321 {
13322 SCIP_CONS* cons0;
13323 SCIP_CONSDATA* consdata0;
13324
13325 cons0 = conss[c];
13326
13327 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13328 continue;
13329
13330 /* do not check for parallel constraints if they should not be upgraded */
13331 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13332 continue;
13333
13334 /* check for interuption */
13335 if( c % 1000 == 0 && SCIPisStopped(scip) )
13336 break;
13337
13338 /* sorts the constraint */
13339 consdata0 = SCIPconsGetData(cons0);
13340 assert(consdata0 != NULL);
13341 SCIP_CALL( consdataSort(scip, consdata0) );
13342 assert(consdata0->indexsorted);
13343
13344 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13345 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13346 * first variable is positive
13347 * Also inserts cons0 into the hashtable.
13348 */
13349 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13350
13351 if( nparallelconss != 0 )
13352 {
13353 SCIP_Real lhs;
13354 SCIP_Real rhs;
13355
13356 int i;
13357
13358 /* cons0 may have been changed in retrieveParallelConstraints() */
13359 consdata0 = SCIPconsGetData(cons0);
13360
13361 lhs = consdata0->lhs;
13362 rhs = consdata0->rhs;
13363
13364 for( i = 0; i < nparallelconss; ++i )
13365 {
13366 SCIP_CONS* consdel;
13367 SCIP_CONSDATA* consdatadel;
13368 SCIP_Real scale;
13369
13370 consdel = parallelconss[i];
13371 consdatadel = SCIPconsGetData(consdel);
13372
13373 /* do not delete constraint if it should not be upgraded */
13374 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13375 continue;
13376
13377 assert(SCIPconsIsActive(consdel));
13378 assert(!SCIPconsIsModifiable(consdel));
13379
13380 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13381 * delete old constraints afterwards
13382 */
13383 assert(consdatadel != NULL);
13384 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13385
13386 assert(consdatadel->indexsorted);
13387 assert(consdata0->vars[0] == consdatadel->vars[0]);
13388
13389 scale = consdata0->vals[0] / consdatadel->vals[0];
13390 assert(scale != 0.0);
13391
13392 /* in debug mode, check that all coefficients are equal with respect to epsilon
13393 * if the constraints are in equilibrium scale
13394 */
13395#ifndef NDEBUG
13396 {
13397 int k;
13398 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13399 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13400
13401 for( k = 0; k < consdata0->nvars; ++k )
13402 {
13403 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13404 }
13405 }
13406#endif
13407
13408 if( scale > 0.0 )
13409 {
13410 /* the coefficients of both constraints are parallel with a positive scale */
13411 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13412 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13413 SCIPdebugPrintCons(scip, cons0, NULL);
13414 SCIPdebugPrintCons(scip, consdel, NULL);
13415
13416 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13417 lhs = MAX(scale * consdatadel->lhs, lhs);
13418
13419 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13420 rhs = MIN(scale * consdatadel->rhs, rhs);
13421 }
13422 else
13423 {
13424 /* the coefficients of both rows are negations */
13425 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13426 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13427 SCIPdebugPrintCons(scip, cons0, NULL);
13428 SCIPdebugPrintCons(scip, consdel, NULL);
13429
13430 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13431 lhs = MAX(scale * consdatadel->rhs, lhs);
13432
13433 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13434 rhs = MIN(scale * consdatadel->lhs, rhs);
13435 }
13436
13437 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13438 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13439
13440 /* delete consdel */
13441 assert( ! consdata0->upgraded || consdatadel->upgraded );
13442 SCIP_CALL( SCIPdelCons(scip, consdel) );
13443 if( !consdatadel->upgraded )
13444 (*ndelconss)++;
13445 }
13446
13447 if( SCIPisFeasLT(scip, rhs, lhs) )
13448 {
13449 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13450 *cutoff = TRUE;
13451 break;
13452 }
13453
13454 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13455 if( lhs > rhs )
13456 {
13457 rhs = (lhs + rhs)/2;
13458 lhs = rhs;
13459 }
13460
13461 /* update lhs and rhs of cons0 */
13462 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13463 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13464
13465 /* update the first changed constraint to begin the next aggregation round with */
13466 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13467 *firstchange = SCIPconsGetPos(cons0);
13468
13469 assert(SCIPconsIsActive(cons0));
13470 }
13471 }
13472#ifdef SCIP_MORE_DEBUG
13473 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13475#endif
13476
13477 SCIPfreeBufferArray(scip, &parallelconss);
13478
13479 /* free hash table */
13480 SCIPhashtableFree(&hashtable);
13481
13482 return SCIP_OKAY;
13483}
13484
13485/** compares constraint with all prior constraints for possible redundancy or aggregation,
13486 * and removes or changes constraint accordingly
13487 */
13488static
13490 SCIP* scip, /**< SCIP data structure */
13491 SCIP_CONS** conss, /**< constraint set */
13492 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13493 int chkind, /**< index of constraint to check against all prior indices upto startind */
13494 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13495 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13496 int* ndelconss, /**< pointer to count number of deleted constraints */
13497 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13498 int* nchgcoefs /**< pointer to count number of changed coefficients */
13499 )
13500{
13501 SCIP_CONS* cons0;
13502 SCIP_CONSDATA* consdata0;
13503 int* commonidx0;
13504 int* commonidx1;
13505 int* diffidx0minus1;
13506 int* diffidx1minus0;
13507 uint64_t possignature0;
13508 uint64_t negsignature0;
13509 SCIP_Bool cons0changed;
13510 SCIP_Bool cons0isequality;
13511 int diffidx1minus0size;
13512 int c;
13513 SCIP_Real cons0lhs;
13514 SCIP_Real cons0rhs;
13515 SCIP_Bool cons0upgraded;
13516
13517 assert(scip != NULL);
13518 assert(conss != NULL);
13519 assert(firstchange <= chkind);
13520 assert(cutoff != NULL);
13521 assert(ndelconss != NULL);
13522 assert(nchgsides != NULL);
13523 assert(nchgcoefs != NULL);
13524
13525 /* get the constraint to be checked against all prior constraints */
13526 cons0 = conss[chkind];
13527 assert(cons0 != NULL);
13528 assert(SCIPconsIsActive(cons0));
13530
13531 consdata0 = SCIPconsGetData(cons0);
13532 assert(consdata0 != NULL);
13533 assert(consdata0->nvars >= 1);
13534 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13535
13536 /* sort the constraint */
13537 SCIP_CALL( consdataSort(scip, consdata0) );
13538
13539 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13540 consdataCalcSignatures(consdata0);
13541 possignature0 = consdata0->possignature;
13542 negsignature0 = consdata0->negsignature;
13543
13544 /* get temporary memory for indices of common variables */
13545 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13546 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13547 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13548 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13549 diffidx1minus0size = consdata0->nvars;
13550
13551 cons0lhs = consdata0->lhs;
13552 cons0rhs = consdata0->rhs;
13553 cons0upgraded = consdata0->upgraded;
13554
13555 /* check constraint against all prior constraints */
13556 cons0changed = consdata0->changed;
13557 consdata0->changed = FALSE;
13558 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13559 {
13560 SCIP_CONS* cons1;
13561 SCIP_CONSDATA* consdata1;
13562 uint64_t possignature1;
13563 uint64_t negsignature1;
13564 SCIP_Bool cons0dominateslhs;
13565 SCIP_Bool cons1dominateslhs;
13566 SCIP_Bool cons0dominatesrhs;
13567 SCIP_Bool cons1dominatesrhs;
13568 SCIP_Bool cons1isequality;
13569 SCIP_Bool coefsequal;
13570 SCIP_Bool coefsnegated;
13571 SCIP_Bool tryaggregation;
13572 int nvarscommon;
13573 int nvars0minus1;
13574 int nvars1minus0;
13575 int commonidxweight;
13576 int diffidx0minus1weight;
13577 int diffidx1minus0weight;
13578 int v0;
13579 int v1;
13580
13581 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13582 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13583 assert(cons0upgraded == consdata0->upgraded);
13584
13585 cons1 = conss[c];
13586
13587 /* cons1 has become inactive during presolving of constraint pairs */
13588 if( cons1 == NULL )
13589 continue;
13590
13591 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13592 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13593
13594 consdata1 = SCIPconsGetData(cons1);
13595 assert(consdata1 != NULL);
13596
13597 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13598 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13599 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13600
13601 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13602 if( !cons0changed && !consdata1->changed )
13603 continue;
13604
13605 /* if both constraints are already upgraded, skip the pair;
13606 * because changes on these constraints cannot be applied to the instance anymore */
13607 if( cons0upgraded && consdata1->upgraded )
13608 continue;
13609
13610 assert(consdata1->nvars >= 1);
13611
13612 /* sort the constraint */
13613 SCIP_CALL( consdataSort(scip, consdata1) );
13614
13615 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13616 consdataCalcSignatures(consdata1);
13617 possignature1 = consdata1->possignature;
13618 negsignature1 = consdata1->negsignature;
13619
13620 /* the signatures give a quick test to check for domination and equality of coefficients */
13621 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13622 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13623 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13624 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13625 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13626 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13627 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13628 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13629 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13630 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13631 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13632 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13633 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13634 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13635 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13636 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13637 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13638 && !coefsequal && !coefsnegated && !tryaggregation )
13639 continue;
13640
13641 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13642 if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13643 {
13644 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13645 diffidx1minus0size = consdata1->nvars;
13646 }
13647
13648 /* check consdata0 against consdata1:
13649 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13650 * consdata0 dominates consdata1 w.r.t. left hand side
13651 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13652 * consdata0 dominates consdata1 w.r.t. right hand side
13653 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13654 * ranged row (or equality)
13655 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13656 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13657 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13658 * number of continuous and integer variables are preferred:
13659 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13660 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13661 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13662 * to be positive to not switch the sense of the (in)equality cons0
13663 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13664 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13665 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13666 * to be positive to not switch the sense of the (in)equality cons1
13667 */
13668
13669 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13670 nvarscommon = 0;
13671 commonidxweight = 0;
13672 nvars0minus1 = 0;
13673 diffidx0minus1weight = 0;
13674 nvars1minus0 = 0;
13675 diffidx1minus0weight = 0;
13676 v0 = 0;
13677 v1 = 0;
13678 while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13679 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13680 || coefsequal || coefsnegated || tryaggregation) )
13681 {
13682 SCIP_VAR* var;
13683 SCIP_Real val0;
13684 SCIP_Real val1;
13685 int varcmp;
13686
13687 /* test, if variable appears in only one or in both constraints */
13688 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13689 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13690 else if( v0 < consdata0->nvars )
13691 varcmp = -1;
13692 else
13693 varcmp = +1;
13694
13695 switch( varcmp )
13696 {
13697 case -1:
13698 /* variable doesn't appear in consdata1 */
13699 var = consdata0->vars[v0];
13700 val0 = consdata0->vals[v0];
13701 val1 = 0.0;
13702 if( tryaggregation )
13703 {
13704 diffidx0minus1[nvars0minus1] = v0;
13705 nvars0minus1++;
13706 diffidx0minus1weight += getVarWeight(var);
13707 }
13708 v0++;
13709 coefsequal = FALSE;
13710 coefsnegated = FALSE;
13711 break;
13712
13713 case +1:
13714 /* variable doesn't appear in consdata0 */
13715 var = consdata1->vars[v1];
13716 val0 = 0.0;
13717 val1 = consdata1->vals[v1];
13718 if( tryaggregation )
13719 {
13720 diffidx1minus0[nvars1minus0] = v1;
13721 nvars1minus0++;
13722 diffidx1minus0weight += getVarWeight(var);
13723 }
13724 v1++;
13725 coefsequal = FALSE;
13726 coefsnegated = FALSE;
13727 break;
13728
13729 case 0:
13730 /* variable appears in both constraints */
13731 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13732 var = consdata0->vars[v0];
13733 val0 = consdata0->vals[v0];
13734 val1 = consdata1->vals[v1];
13735 if( tryaggregation )
13736 {
13737 commonidx0[nvarscommon] = v0;
13738 commonidx1[nvarscommon] = v1;
13739 nvarscommon++;
13740 commonidxweight += getVarWeight(var);
13741 }
13742 v0++;
13743 v1++;
13744 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13745 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13746 break;
13747
13748 default:
13749 SCIPerrorMessage("invalid comparison result\n");
13750 SCIPABORT();
13751 var = NULL;
13752 val0 = 0.0;
13753 val1 = 0.0;
13754 }
13755 assert(var != NULL);
13756
13757 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13758 if( SCIPisGT(scip, val0, val1) )
13759 {
13761 {
13762 cons0dominatesrhs = FALSE;
13763 cons1dominateslhs = FALSE;
13764 }
13766 {
13767 cons0dominateslhs = FALSE;
13768 cons1dominatesrhs = FALSE;
13769 }
13770 }
13771 else if( SCIPisLT(scip, val0, val1) )
13772 {
13774 {
13775 cons0dominateslhs = FALSE;
13776 cons1dominatesrhs = FALSE;
13777 }
13779 {
13780 cons0dominatesrhs = FALSE;
13781 cons1dominateslhs = FALSE;
13782 }
13783 }
13784 }
13785
13786 /* check for disaggregated ranged rows */
13787 if( coefsequal || coefsnegated )
13788 {
13789 SCIP_CONS* consstay;
13790 SCIP_CONS* consdel;
13791#ifndef NDEBUG
13792 SCIP_CONSDATA* consdatastay;
13793#endif
13794 SCIP_CONSDATA* consdatadel;
13795 SCIP_Real lhs;
13796 SCIP_Real rhs;
13797 int consinddel;
13798
13799 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13800 * best left and right hand sides; delete the old constraints afterwards
13801 */
13802 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13803 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13804 SCIPdebugPrintCons(scip, cons0, NULL);
13805 SCIPdebugPrintCons(scip, cons1, NULL);
13806
13807 if( coefsequal )
13808 {
13809 /* the coefficients of both rows are equal */
13810 lhs = MAX(consdata0->lhs, consdata1->lhs);
13811 rhs = MIN(consdata0->rhs, consdata1->rhs);
13812 }
13813 else
13814 {
13815 /* the coefficients of both rows are negations */
13816 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13817 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13818 }
13819 if( SCIPisFeasLT(scip, rhs, lhs) )
13820 {
13821 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13822 *cutoff = TRUE;
13823 break;
13824 }
13825
13826 /* check which constraint has to stay;
13827 * changes applied to an upgraded constraint will not be considered in the instance */
13828 if( consdata0->upgraded )
13829 {
13830 assert(!consdata1->upgraded);
13831 consstay = cons1;
13832#ifndef NDEBUG
13833 consdatastay = consdata1;
13834#endif
13835
13836 consdel = cons0;
13837 consdatadel = consdata0;
13838 consinddel = chkind;
13839 }
13840 else
13841 {
13842 consstay = cons0;
13843#ifndef NDEBUG
13844 consdatastay = consdata0;
13845#endif
13846
13847 consdel = cons1;
13848 consdatadel = consdata1;
13849 consinddel = c;
13850 }
13851
13852 /* update the sides of consstay */
13853 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13854 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13855 if( !consdata0->upgraded )
13856 {
13857 assert(consstay == cons0);
13858 cons0lhs = consdata0->lhs;
13859 cons0rhs = consdata0->rhs;
13860 }
13861
13862 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13863 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13864
13865 assert( !consdatastay->upgraded );
13866 /* delete consdel */
13867 SCIP_CALL( SCIPdelCons(scip, consdel) );
13868 conss[consinddel] = NULL;
13869 if( !consdatadel->upgraded )
13870 (*ndelconss)++;
13871 continue;
13872 }
13873
13874 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13875 * redundant
13876 */
13877 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13878 {
13879 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13880 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13881 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13882 SCIPdebugPrintCons(scip, cons0, NULL);
13883 SCIPdebugPrintCons(scip, cons1, NULL);
13884
13885 /* check for infeasibility */
13886 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13887 {
13888 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13889 *cutoff = TRUE;
13890 break;
13891 }
13892
13893 /* remove redundant left hand side */
13894 if( !SCIPisInfinity(scip, -consdata0->lhs) )
13895 {
13896 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13897 cons0lhs = consdata0->lhs;
13898 cons0isequality = FALSE;
13899 if( !consdata0->upgraded )
13900 {
13901 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13902 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13903
13904 (*nchgsides)++;
13905 }
13906 }
13907 }
13908 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13909 {
13910 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13911 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13912 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13913 SCIPdebugPrintCons(scip, cons1, NULL);
13914 SCIPdebugPrintCons(scip, cons0, NULL);
13915
13916 /* check for infeasibility */
13917 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13918 {
13919 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13920 *cutoff = TRUE;
13921 break;
13922 }
13923
13924 /* remove redundant left hand side */
13925 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13926 {
13927 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13928 cons1isequality = FALSE;
13929 if( !consdata1->upgraded )
13930 {
13931 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13932 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13933
13934 (*nchgsides)++;
13935 }
13936 }
13937 }
13938 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13939 {
13940 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13941 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13942 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13943 SCIPdebugPrintCons(scip, cons0, NULL);
13944 SCIPdebugPrintCons(scip, cons1, NULL);
13945
13946 /* check for infeasibility */
13947 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13948 {
13949 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13950 *cutoff = TRUE;
13951 break;
13952 }
13953
13954 /* remove redundant right hand side */
13955 if( !SCIPisInfinity(scip, consdata0->rhs) )
13956 {
13957 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13958 cons0rhs = consdata0->rhs;
13959 cons0isequality = FALSE;
13960 if( !consdata0->upgraded )
13961 {
13962 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13963 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13964
13965 (*nchgsides)++;
13966 }
13967 }
13968 }
13969 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13970 {
13971 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13972 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13973 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13974 SCIPdebugPrintCons(scip, cons1, NULL);
13975 SCIPdebugPrintCons(scip, cons0, NULL);
13976
13977 /* check for infeasibility */
13978 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13979 {
13980 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13981 *cutoff = TRUE;
13982 break;
13983 }
13984
13985 /* remove redundant right hand side */
13986 if( !SCIPisInfinity(scip, consdata1->rhs) )
13987 {
13988 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13989 cons1isequality = FALSE;
13990 if( !consdata1->upgraded )
13991 {
13992 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13993 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13994
13995 (*nchgsides)++;
13996 }
13997 }
13998 }
13999
14000 /* check for now redundant constraints */
14001 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
14002 {
14003 /* consdata0 became redundant */
14004 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
14005 SCIP_CALL( SCIPdelCons(scip, cons0) );
14006 conss[chkind] = NULL;
14007 if( !consdata0->upgraded )
14008 {
14009 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14010 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
14011
14012 (*ndelconss)++;
14013 }
14014 continue;
14015 }
14016 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
14017 {
14018 /* consdata1 became redundant */
14019 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
14020 SCIP_CALL( SCIPdelCons(scip, cons1) );
14021 conss[c] = NULL;
14022 if( !consdata1->upgraded )
14023 {
14024 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14025 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
14026
14027 (*ndelconss)++;
14028 }
14029 continue;
14030 }
14031
14032 /* check, if we want to aggregate an (in)equality with an equality:
14033 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
14034 */
14035 if( tryaggregation )
14036 {
14037 SCIP_Bool aggregated;
14038
14039 assert(consdata0->nvars == nvarscommon + nvars0minus1);
14040 assert(consdata1->nvars == nvarscommon + nvars1minus0);
14041
14042 aggregated = FALSE;
14043 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
14044 {
14045 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
14046 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
14047 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
14048 nchgcoefs, &aggregated, cutoff) );
14049
14050 if( *cutoff )
14051 break;
14052
14053 /* update array of active constraints */
14054 if( aggregated )
14055 {
14056 assert(!SCIPconsIsActive(cons0));
14057 assert(SCIPconsIsActive(cons1));
14058 conss[chkind] = NULL;
14059 }
14060 }
14061 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
14062 {
14063 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
14064 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
14065 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
14066 nchgcoefs, &aggregated, cutoff) );
14067
14068 if( *cutoff )
14069 break;
14070
14071 /* update array of active constraints */
14072 if( aggregated )
14073 {
14074 assert(!SCIPconsIsActive(cons1));
14075 assert(SCIPconsIsActive(cons0));
14076 conss[c] = NULL;
14077 }
14078 }
14079 }
14080 }
14081
14082 /* free temporary memory */
14083 SCIPfreeBufferArray(scip, &diffidx1minus0);
14084 SCIPfreeBufferArray(scip, &diffidx0minus1);
14085 SCIPfreeBufferArray(scip, &commonidx1);
14086 SCIPfreeBufferArray(scip, &commonidx0);
14087
14088 return SCIP_OKAY;
14089}
14090
14091/** do stuffing presolving on a single constraint */
14092static
14094 SCIP* scip, /**< SCIP data structure */
14095 SCIP_CONS* cons, /**< linear constraint */
14096 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14097 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14098 * constraints using the cheapest variable? */
14099 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14100 int* nfixedvars, /**< pointer to count the total number of fixed variables */
14101 int* nchgbds /**< pointer to count the total number of tightened bounds */
14102 )
14103{
14104 SCIP_CONSDATA* consdata;
14105 SCIP_Real* ratios;
14106 int* varpos;
14107 SCIP_Bool* swapped;
14108 SCIP_VAR** vars;
14109 SCIP_Real* vals;
14110 SCIP_VAR* var;
14111 SCIP_Real lb;
14112 SCIP_Real ub;
14113 SCIP_Real minactivity;
14114 SCIP_Real maxactivity;
14115 SCIP_Real maxcondactivity;
14116 SCIP_Real mincondactivity;
14117 SCIP_Real rhs;
14118 SCIP_Real val;
14119 SCIP_Real obj;
14120 SCIP_Real factor;
14121 SCIP_Bool isminacttight;
14122 SCIP_Bool ismaxacttight;
14123 SCIP_Bool isminsettoinfinity;
14124 SCIP_Bool ismaxsettoinfinity;
14125 SCIP_Bool tryfixing;
14126 int nsingletons;
14127 int idx;
14128 int v;
14129 int nvars;
14130
14131 assert(scip != NULL);
14132 assert(cons != NULL);
14133 assert(nfixedvars != NULL);
14134
14135 consdata = SCIPconsGetData(cons);
14136
14137 /* we only want to run for inequalities */
14138 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14139 return SCIP_OKAY;
14140
14141 if( singlevarstuffing )
14142 {
14143 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
14144 &isminsettoinfinity, &ismaxsettoinfinity);
14145 }
14146 else
14147 {
14148 minactivity = SCIP_INVALID;
14149 maxactivity = SCIP_INVALID;
14150 isminsettoinfinity = FALSE;
14151 ismaxsettoinfinity = FALSE;
14152 }
14153
14154 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14155 * the new maxactivity is minus the old minactivity then
14156 */
14157 if( SCIPisInfinity(scip, consdata->rhs) )
14158 {
14159 rhs = -consdata->lhs;
14160 factor = -1.0;
14161 maxactivity = -minactivity;
14162 ismaxsettoinfinity = isminsettoinfinity;
14163 }
14164 else
14165 {
14166 assert(SCIPisInfinity(scip, -consdata->lhs));
14167 rhs = consdata->rhs;
14168 factor = 1.0;
14169 }
14170
14171 nvars = consdata->nvars;
14172 vars = consdata->vars;
14173 vals = consdata->vals;
14174
14175 /* check for continuous singletons */
14176 if( singletonstuffing )
14177 {
14178 for( v = 0; v < nvars; ++v )
14179 {
14180 var = vars[v];
14181
14184 break;
14185 }
14186 }
14187 else
14188 /* we don't want to go into the next block */
14189 v = nvars;
14190
14191 /* a singleton was found -> perform singleton variable stuffing */
14192 if( v < nvars )
14193 {
14194 assert(singletonstuffing);
14195
14199
14200 tryfixing = TRUE;
14201 nsingletons = 0;
14202 mincondactivity = 0.0;
14203 maxcondactivity = 0.0;
14204
14205 for( v = 0; v < nvars; ++v )
14206 {
14207 var = vars[v];
14208 lb = SCIPvarGetLbGlobal(var);
14209 ub = SCIPvarGetUbGlobal(var);
14211 val = factor * vals[v];
14212
14213 assert(!SCIPisZero(scip, val));
14214
14215 /* the variable is a singleton and continuous */
14218 {
14219 if( SCIPisNegative(scip, obj) && val > 0 )
14220 {
14221 /* case 1: obj < 0 and coef > 0 */
14222 if( SCIPisInfinity(scip, -lb) )
14223 {
14224 tryfixing = FALSE;
14225 break;
14226 }
14227
14228 maxcondactivity += val * lb;
14229 mincondactivity += val * lb;
14230 swapped[v] = FALSE;
14231 ratios[nsingletons] = obj / val;
14232 varpos[nsingletons] = v;
14233 nsingletons++;
14234 }
14235 else if( SCIPisPositive(scip, obj) && val < 0 )
14236 {
14237 /* case 2: obj > 0 and coef < 0 */
14238 if( SCIPisInfinity(scip, ub) )
14239 {
14240 tryfixing = FALSE;
14241 break;
14242 }
14243 /* multiply column by (-1) to become case 1.
14244 * now bounds are swapped: ub := -lb, lb := -ub
14245 */
14246
14247 maxcondactivity += val * ub;
14248 mincondactivity += val * ub;
14249 swapped[v] = TRUE;
14250 ratios[nsingletons] = obj / val;
14251 varpos[nsingletons] = v;
14252 nsingletons++;
14253 }
14254 else if( val > 0 )
14255 {
14256 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14257 * we only consider the lower bound for the constants
14258 */
14260
14261 if( SCIPisInfinity(scip, -lb) )
14262 {
14263 /* maybe unbounded */
14264 tryfixing = FALSE;
14265 break;
14266 }
14267
14268 maxcondactivity += val * lb;
14269 mincondactivity += val * lb;
14270 }
14271 else
14272 {
14273 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14274 * we only consider the upper bound for the constants
14275 */
14277 assert(val < 0);
14278
14279 if( SCIPisInfinity(scip, ub) )
14280 {
14281 /* maybe unbounded */
14282 tryfixing = FALSE;
14283 break;
14284 }
14285
14286 maxcondactivity += val * ub;
14287 mincondactivity += val * ub;
14288 }
14289 }
14290 else
14291 {
14292 /* consider contribution of discrete variables, non-singleton
14293 * continuous variables and variables with more than one lock
14294 */
14295 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14296 {
14297 tryfixing = FALSE;
14298 break;
14299 }
14300
14301 if( val > 0 )
14302 {
14303 maxcondactivity += val * ub;
14304 mincondactivity += val * lb;
14305 }
14306 else
14307 {
14308 maxcondactivity += val * lb;
14309 mincondactivity += val * ub;
14310 }
14311 }
14312 }
14313 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14314 {
14315 SCIP_Real delta;
14316 SCIP_Bool tightened;
14317#ifdef SCIP_DEBUG
14318 int oldnfixedvars = *nfixedvars;
14319 int oldnchgbds = *nchgbds;
14320#endif
14321
14322 SCIPsortRealInt(ratios, varpos, nsingletons);
14323
14324 /* verify which singleton continuous variables can be fixed */
14325 for( v = 0; v < nsingletons; ++v )
14326 {
14327 idx = varpos[v];
14328 var = vars[idx];
14329 val = factor * vals[idx];
14330 lb = SCIPvarGetLbGlobal(var);
14331 ub = SCIPvarGetUbGlobal(var);
14332
14334 assert((val < 0) == swapped[idx]);
14335 val = REALABS(val);
14336
14337 /* stop fixing if variable bounds are not finite */
14338 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14339 break;
14340
14344
14345 /* calculate the change in the row activities if this variable changes
14346 * its value from its worst to its best bound
14347 */
14348 if( swapped[idx] )
14349 delta = -(lb - ub) * val;
14350 else
14351 delta = (ub - lb) * val;
14352
14353 assert(!SCIPisNegative(scip, delta));
14354
14355 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14356 {
14357 if( swapped[idx] )
14358 {
14359 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14360 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14361 }
14362 else
14363 {
14364 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14365 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14366 }
14367
14368 if( *cutoff )
14369 break;
14370 if( tightened )
14371 {
14372 (*nfixedvars)++;
14373 }
14374 }
14375 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14376 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14377 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14378 * troubles in case of large bounds.
14379 */
14380 else if( SCIPisLE(scip, rhs, mincondactivity) )
14381 {
14382 if( swapped[idx] )
14383 {
14384 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14385 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14386 }
14387 else
14388 {
14389 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14390 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14391 }
14392
14393 if( *cutoff )
14394 break;
14395 if( tightened )
14396 {
14397 (*nfixedvars)++;
14398 }
14399 }
14400
14401 maxcondactivity += delta;
14402 mincondactivity += delta;
14403 }
14404
14405#ifdef SCIP_DEBUG
14406 if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14407 {
14408 SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14409 }
14410#endif
14411 }
14412
14413 SCIPfreeBufferArray(scip, &swapped);
14414 SCIPfreeBufferArray(scip, &ratios);
14415 SCIPfreeBufferArray(scip, &varpos);
14416 }
14417
14418 /* perform single-variable stuffing:
14419 * for a linear inequality
14420 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14421 * with a_i > 0 and objective coefficients c_i < 0,
14422 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14423 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14424 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14425 * is redundant.
14426 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14427 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14428 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14429 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14430 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14431 * upper bound.
14432 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14433 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14434 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14435 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14436 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14437 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14438 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14439 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14440 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14441 * c_k * ceil((maxactivity - rhs)/val) is still better than
14442 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14443 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14444 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14445 * sign of coefficients in constraint and objective prevent the use of this method.
14446 */
14447 if( singlevarstuffing && !ismaxsettoinfinity )
14448 {
14449 SCIP_Real bestratio = -SCIPinfinity(scip);
14450 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14451 SCIP_Real ratio;
14452 int bestindex = -1;
14453 int bestuplocks = 0;
14454 int bestdownlocks = 1;
14455 int downlocks;
14456 int uplocks;
14457 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14458 SCIPdebug( int oldnchgbds = *nchgbds; )
14459
14460 /* loop over all variables to identify the best and second-best ratio */
14461 for( v = 0; v < nvars; ++v )
14462 {
14463 var = vars[v];
14465 val = factor * vals[v];
14466
14467 assert(!SCIPisZero(scip, val));
14468
14469 ratio = obj / val;
14470
14471 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14472 if( !SCIPisNegative(scip, ratio) )
14473 {
14474 bestindex = -1;
14475 break;
14476 }
14477
14478 if( val > 0 )
14479 {
14482 }
14483 else
14484 {
14487 }
14488
14489 /* better ratio, update best candidate
14490 * @todo use some tolerance
14491 * @todo check size of domain and updated ratio for integer variables already?
14492 */
14493 if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14496 {
14497 /* best index becomes second-best*/
14498 if( bestindex != -1 )
14499 {
14500 /* second-best index must not have more than 1 uplock */
14501 if( bestuplocks > 1 )
14502 {
14503 bestindex = -1;
14504 break;
14505 }
14506 else
14507 {
14508 secondbestratio = bestratio;
14509 }
14510 }
14511 bestdownlocks = downlocks;
14512 bestuplocks = uplocks;
14513 bestratio = ratio;
14514 bestindex = v;
14515
14516 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14517 * if it is not the best, it has too many uplocks -> not applicable
14518 */
14519 if( bestdownlocks > 0 && bestuplocks > 1 )
14520 {
14521 bestindex = -1;
14522 break;
14523 }
14524 }
14525 else
14526 {
14527 /* non-best index must not have more than 1 uplock */
14528 if( uplocks > 1 )
14529 {
14530 bestindex = -1;
14531 break;
14532 }
14533 /* update second-best ratio */
14534 if( ratio > secondbestratio )
14535 {
14536 secondbestratio = ratio;
14537 }
14538 }
14539 }
14540
14541 /* check if we can apply single variable stuffing */
14542 if( bestindex != -1 && bestdownlocks == 0 )
14543 {
14544 SCIP_Bool tightened = FALSE;
14545 SCIP_Real bounddelta;
14546
14547 var = vars[bestindex];
14549 val = factor * vals[bestindex];
14550 lb = SCIPvarGetLbGlobal(var);
14551 ub = SCIPvarGetUbGlobal(var);
14552 tryfixing = TRUE;
14553
14554 if( val < 0 )
14555 {
14557
14558 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14559 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14560 {
14561 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14562 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14563 assert(SCIPisPositive(scip, activitydelta));
14564
14565 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14566
14567 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14568 assert(SCIPisPositive(scip, bounddelta));
14569 }
14570 else
14571 bounddelta = (maxactivity - rhs)/-val;
14572
14573 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14574
14575 if( tryfixing )
14576 {
14578
14579 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14580 {
14581 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14582 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14583 }
14584 else
14585 {
14586 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14587 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14588 }
14589 }
14590 }
14591 else
14592 {
14594
14595 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14596 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14597 {
14598 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14599 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14600 assert(SCIPisPositive(scip, activitydelta));
14601
14602 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14603
14604 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14605 assert(SCIPisPositive(scip, bounddelta));
14606 }
14607 else
14608 bounddelta = (maxactivity - rhs)/val;
14609
14610 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14611
14612 if( tryfixing )
14613 {
14615
14616 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14617 {
14618 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14619 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14620 }
14621 else
14622 {
14623 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14624 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14625 }
14626 }
14627 }
14628
14629 if( *cutoff )
14630 return SCIP_OKAY;
14631 if( tightened )
14632 {
14634 ++(*nfixedvars);
14635 else
14636 ++(*nchgbds);
14637
14638 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14639 for( v = 0; v < nvars; ++v )
14640 {
14641 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14645 SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14646 }
14647 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14648
14649 for( v = 0; v < nvars; ++v )
14650 {
14651 if( v == bestindex )
14652 continue;
14653
14654 if( factor * vals[v] < 0 )
14655 {
14657 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14659 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14660 }
14661 else
14662 {
14664 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14666 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14667 }
14668
14669 if( *cutoff )
14670 return SCIP_OKAY;
14671 if( tightened )
14672 ++(*nfixedvars);
14673 }
14674 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14675 }
14676 }
14677 }
14678
14679 return SCIP_OKAY;
14680}
14681
14682/** applies full dual presolving on variables that only appear in linear constraints */
14683static
14685 SCIP* scip, /**< SCIP data structure */
14686 SCIP_CONS** conss, /**< constraint set */
14687 int nconss, /**< number of constraints */
14688 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14689 int* nchgbds /**< pointer to count the number of bound changes */
14690 )
14691{
14692 SCIP_Real* redlb;
14693 SCIP_Real* redub;
14694 int* nlocksdown;
14695 int* nlocksup;
14696 SCIP_Bool* isimplint;
14697 SCIP_VAR** origvars;
14698 SCIP_VAR** vars;
14699 SCIP_VAR** conscontvars;
14700 int nvars;
14701 int nbinvars;
14702 int nintvars;
14703 int ncontvars;
14704 int v;
14705 int c;
14706
14707 /* we calculate redundancy bounds with the following meaning:
14708 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14709 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14710 * then:
14711 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14712 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14713 */
14714
14715 /* Additionally, we detect continuous variables that are implicitly integral.
14716 * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14717 * and all constraints (including the bounds as trivial constraints) in which:
14718 * c_j > 0: the variable is down-locked,
14719 * c_j < 0: the variable is up-locked,
14720 * c_j = 0: the variable appears
14721 * have, apart from j, only integer variables with integral coefficients and integral sides.
14722 * This is because then, the value of the variable is either determined by one of its bounds or
14723 * by one of these constraints, and in all cases, the value of the variable is integral.
14724 */
14725
14726 assert(scip != NULL);
14727 assert(nconss == 0 || conss != NULL);
14728 assert(nchgbds != NULL);
14730
14731 /* get active variables */
14733 origvars = SCIPgetVars(scip);
14734
14735 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14737 if( nbinvars == nvars )
14738 return SCIP_OKAY;
14739
14740 /* get number of continuous variables */
14741 ncontvars = SCIPgetNContVars(scip);
14742 nintvars = nvars - ncontvars;
14743
14744 /* copy the variable array since this array might change during the curse of this algorithm */
14745 nvars = nvars - nbinvars;
14747
14748 /* allocate temporary memory */
14751 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14752 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14753 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14754 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14755
14756 /* initialize redundancy bounds */
14757 for( v = 0; v < nvars; ++v )
14758 {
14760 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14761 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14762 }
14763 BMSclearMemoryArray(nlocksdown, nvars);
14764 BMSclearMemoryArray(nlocksup, nvars);
14765
14766 /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14767 * We better not use SCIPisFeasIntegral() in these checks.
14768 */
14769 for( v = 0; v < ncontvars; v++ )
14770 {
14771 SCIP_VAR* var;
14772 SCIP_Real obj;
14773 SCIP_Real lb;
14774 SCIP_Real ub;
14775
14776 var = vars[v + nintvars - nbinvars];
14777 lb = SCIPvarGetLbGlobal(var);
14778 ub = SCIPvarGetUbGlobal(var);
14779
14781 if( SCIPisZero(scip, obj) )
14782 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14783 else
14784 {
14785 if( SCIPisPositive(scip, obj) )
14786 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14787 else
14788 {
14790 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14791 }
14792 }
14793 }
14794
14795 /* scan all constraints */
14796 for( c = 0; c < nconss; ++c )
14797 {
14798 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14799 * part of checked disjunctions)
14800 */
14801 if( SCIPconsIsLocked(conss[c]) )
14802 {
14803 SCIP_CONSDATA* consdata;
14804 SCIP_Bool lhsexists;
14805 SCIP_Bool rhsexists;
14806 SCIP_Bool hasimpliedpotential;
14807 SCIP_Bool integralcoefs;
14808 int nlockspos;
14809 int contvarpos;
14810 int nconscontvars;
14811 int i;
14812
14813 consdata = SCIPconsGetData(conss[c]);
14814 assert(consdata != NULL);
14815
14816 /* get number of times the constraint was locked */
14817 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14818
14819 /* we do not want to include constraints with locked negation (this would be too weird) */
14820 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14821 {
14822 /* mark all continuous variables as not being implicit integral */
14823 for( i = 0; i < consdata->nvars; ++i )
14824 {
14825 SCIP_VAR* var;
14826
14827 var = consdata->vars[i];
14829 {
14830 int contv;
14831 contv = SCIPvarGetProbindex(var) - nintvars;
14832 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14833 isimplint[contv] = FALSE;
14834 }
14835 }
14836 continue;
14837 }
14838
14839 /* check for existing sides */
14840 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14841 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14842
14843 /* count locks and update redundancy bounds */
14844 contvarpos = -1;
14845 nconscontvars = 0;
14846 hasimpliedpotential = FALSE;
14847 integralcoefs = !SCIPconsIsModifiable(conss[c]);
14848
14849 for( i = 0; i < consdata->nvars; ++i )
14850 {
14851 SCIP_VAR* var;
14852 SCIP_Real val;
14853 SCIP_Real minresactivity;
14854 SCIP_Real maxresactivity;
14855 SCIP_Real newredlb;
14856 SCIP_Real newredub;
14857 SCIP_Bool ismintight;
14858 SCIP_Bool ismaxtight;
14859 SCIP_Bool isminsettoinfinity;
14860 SCIP_Bool ismaxsettoinfinity;
14861 int arrayindex;
14862
14863 var = consdata->vars[i];
14864 val = consdata->vals[i];
14865
14866 /* check if still all integer variables have integral coefficients */
14867 if( SCIPvarIsIntegral(var) )
14868 integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14869
14870 /* we do not need to process binary variables */
14871 if( SCIPvarIsBinary(var) )
14872 continue;
14873
14874 if( SCIPconsIsModifiable(conss[c]) )
14875 {
14876 minresactivity = -SCIPinfinity(scip);
14877 maxresactivity = SCIPinfinity(scip);
14878 isminsettoinfinity = TRUE;
14879 ismaxsettoinfinity = TRUE;
14880 }
14881 else
14882 {
14883 /* calculate residual activity bounds if variable would be fixed to zero */
14884 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14885 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
14886
14887 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14888 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14889 * This is needed, because we do not want to rely on relaxed finite resactivities.
14890 */
14891 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
14892
14893 /* check minresactivity for reliability */
14894 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14895 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14896
14897 /* check maxresactivity for reliability */
14898 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14899 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14900 }
14901
14902 arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14903
14904 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14905
14906 newredlb = redlb[arrayindex];
14907 newredub = redub[arrayindex];
14908 if( val > 0.0 )
14909 {
14910 if( lhsexists )
14911 {
14912 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14913 nlocksdown[arrayindex] += nlockspos;
14914 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14915 }
14916 if( rhsexists )
14917 {
14918 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14919 nlocksup[arrayindex] += nlockspos;
14920 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14921 }
14922 }
14923 else
14924 {
14925 if( lhsexists )
14926 {
14927 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14928 nlocksup[arrayindex] += nlockspos;
14929 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14930 }
14931 if( rhsexists )
14932 {
14933 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14934 nlocksdown[arrayindex] += nlockspos;
14935 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14936 }
14937 }
14938
14939 /* if the variable is integer, we have to round the value to the next integral value */
14940 if( SCIPvarIsIntegral(var) )
14941 {
14942 if( !SCIPisInfinity(scip, newredlb) )
14943 newredlb = SCIPceil(scip, newredlb);
14944 if( !SCIPisInfinity(scip, -newredub) )
14945 newredub = SCIPfloor(scip, newredub);
14946 }
14947
14948 /* update redundancy bounds */
14949 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14950 redub[arrayindex] = MIN(redub[arrayindex], newredub);
14951
14952 /* collect the continuous variables of the constraint */
14954 {
14955 int contv;
14956
14957 assert(nconscontvars < ncontvars);
14958 contvarpos = i;
14959 conscontvars[nconscontvars] = var;
14960 nconscontvars++;
14961
14962 contv = SCIPvarGetProbindex(var) - nintvars;
14963 assert(0 <= contv && contv < ncontvars);
14964 hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14965 }
14966 }
14967
14968 /* update implicit integer status of continuous variables */
14969 if( hasimpliedpotential )
14970 {
14971 if( nconscontvars > 1 || !integralcoefs )
14972 {
14973 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14974 * none of the continuous variables is implicit integer
14975 */
14976 for( i = 0; i < nconscontvars; i++ )
14977 {
14978 int contv;
14979 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14980 assert(0 <= contv && contv < ncontvars);
14981 isimplint[contv] = FALSE;
14982 }
14983 }
14984 else
14985 {
14986 SCIP_VAR* var;
14987 SCIP_Real val;
14988 SCIP_Real absval;
14989 int contv;
14990
14991 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14992 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14993 * side(s) of the constraint is integral
14994 */
14995 assert(nconscontvars == 1);
14996 assert(0 <= contvarpos && contvarpos < consdata->nvars);
14997 var = consdata->vars[contvarpos];
14998 val = consdata->vals[contvarpos];
14999 contv = SCIPvarGetProbindex(var) - nintvars;
15000 assert(0 <= contv && contv < ncontvars);
15001 assert(isimplint[contv]);
15002
15003 absval = REALABS(val);
15004 if( !SCIPisEQ(scip, absval, 1.0) )
15005 isimplint[contv] = FALSE;
15006 else
15007 {
15008 SCIP_Real obj;
15009
15011 if( obj * val >= 0.0 && lhsexists )
15012 {
15013 /* the variable may be blocked by the constraint's left hand side */
15014 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
15015 }
15016 if( obj * val <= 0.0 && rhsexists )
15017 {
15018 /* the variable may be blocked by the constraint's left hand side */
15019 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
15020 }
15021 }
15022 }
15023 }
15024 }
15025 }
15026
15027 /* check if any bounds can be tightened due to optimality */
15028 for( v = 0; v < nvars; ++v )
15029 {
15030 SCIP_VAR* var;
15031 SCIP_Real obj;
15032 SCIP_Bool infeasible;
15033 SCIP_Bool tightened;
15034
15038
15039 var = vars[v];
15041 if( !SCIPisPositive(scip, -obj) )
15042 {
15043 /* making the variable as small as possible does not increase the objective:
15044 * check if all down locks of the variables are due to linear constraints;
15045 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
15046 * constraints redundant is huge, we better do nothing for numerical reasons
15047 */
15050 && !SCIPisHugeValue(scip, -redlb[v])
15051 && redlb[v] < SCIPvarGetUbGlobal(var) )
15052 {
15053 SCIP_Real ub;
15054
15055 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
15056 * -> tighten upper bound to x_v <= redlb[v]
15057 */
15058 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
15060 redlb[v]);
15061 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
15062 assert(!infeasible);
15063
15064 ub = SCIPvarGetUbGlobal(var);
15065 redub[v] = MIN(redub[v], ub);
15066 if( tightened )
15067 (*nchgbds)++;
15068 }
15069 }
15070 if( !SCIPisPositive(scip, obj) )
15071 {
15072 /* making the variable as large as possible does not increase the objective:
15073 * check if all up locks of the variables are due to linear constraints;
15074 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
15075 * constraints redundant is huge, we better do nothing for numerical reasons
15076 */
15079 && !SCIPisHugeValue(scip, redub[v])
15080 && redub[v] > SCIPvarGetLbGlobal(var) )
15081 {
15082 SCIP_Real lb;
15083
15084 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
15085 * -> tighten lower bound to x_v >= redub[v]
15086 */
15087 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
15089 redub[v]);
15090 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15091 assert(!infeasible);
15092
15093 lb = SCIPvarGetLbGlobal(var);
15094 redlb[v] = MAX(redlb[v], lb);
15095 if( tightened )
15096 (*nchgbds)++;
15097 }
15098 }
15099 }
15100
15101 /* upgrade continuous variables to implicit integers */
15102 for( v = nintvars - nbinvars; v < nvars; ++v )
15103 {
15104 SCIP_VAR* var;
15105 SCIP_Bool infeasible;
15106
15107 var = vars[v];
15108 assert(var != NULL);
15109
15113 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15114
15115 /* we can only conclude implicit integrality if the variable appears in no other constraint */
15116 if( isimplint[v - nintvars + nbinvars]
15118 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15119 {
15120 /* since we locally copied the variable array we can change the variable type immediately */
15122
15123 if( infeasible )
15124 {
15125 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15126 *cutoff = TRUE;
15127
15128 break;
15129 }
15130
15131 SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15133 }
15134 }
15135
15136 /* free temporary memory */
15137 SCIPfreeBufferArray(scip, &conscontvars);
15138 SCIPfreeBufferArray(scip, &isimplint);
15139 SCIPfreeBufferArray(scip, &nlocksup);
15140 SCIPfreeBufferArray(scip, &nlocksdown);
15141 SCIPfreeBufferArray(scip, &redub);
15142 SCIPfreeBufferArray(scip, &redlb);
15143
15145
15146 return SCIP_OKAY;
15147}
15148
15149/** helper function to enforce constraints */
15150static
15152 SCIP* scip, /**< SCIP data structure */
15153 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15154 SCIP_CONS** conss, /**< constraints to process */
15155 int nconss, /**< number of constraints */
15156 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15157 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15158 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15159 )
15160{
15161 SCIP_CONSHDLRDATA* conshdlrdata;
15162 SCIP_Bool checkrelmaxabs;
15163 SCIP_Bool violated;
15164 SCIP_Bool cutoff = FALSE;
15165 int c;
15166
15167 assert(scip != NULL);
15168 assert(conshdlr != NULL);
15169 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15170 assert(result != NULL);
15171
15172 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15173 assert(conshdlrdata != NULL);
15174
15175 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15176
15177 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15178
15179 /* check for violated constraints
15180 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15181 */
15183
15184 /* check all useful linear constraints for feasibility */
15185 for( c = 0; c < nusefulconss; ++c )
15186 {
15187 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15188
15189 if( violated )
15190 {
15191 /* insert LP row as cut */
15192 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15193 if ( cutoff )
15195 else
15197 }
15198 }
15199
15200 /* check all obsolete linear constraints for feasibility */
15201 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15202 {
15203 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15204
15205 if( violated )
15206 {
15207 /* insert LP row as cut */
15208 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15209 if ( cutoff )
15211 else
15213 }
15214 }
15215
15216 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15217
15218 return SCIP_OKAY;
15219}
15220
15221/** adds symmetry information of constraint to a symmetry detection graph */
15222static
15224 SCIP* scip, /**< SCIP pointer */
15225 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15226 SCIP_CONS* cons, /**< constraint */
15227 SYM_GRAPH* graph, /**< symmetry detection graph */
15228 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15229 )
15230{
15231 SCIP_CONSDATA* consdata;
15232 SCIP_VAR** vars;
15233 SCIP_Real* vals;
15234 SCIP_Real constant = 0.0;
15235 SCIP_Real lhs;
15236 SCIP_Real rhs;
15237 int nlocvars;
15238 int nvars;
15239 int i;
15240
15241 assert(scip != NULL);
15242 assert(cons != NULL);
15243 assert(graph != NULL);
15244 assert(success != NULL);
15245
15246 consdata = SCIPconsGetData(cons);
15247 assert(consdata != NULL);
15248
15249 /* get active variables of the constraint */
15251 nlocvars = consdata->nvars;
15252
15255
15256 for( i = 0; i < nlocvars; ++i )
15257 {
15258 vars[i] = consdata->vars[i];
15259 vals[i] = consdata->vals[i];
15260 }
15261
15262 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15263 lhs = consdata->lhs - constant;
15264 rhs = consdata->rhs - constant;
15265
15266 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15267 * of the same constraint are rated as equal
15268 */
15269 if ( SCIPisInfinity(scip, rhs) )
15270 {
15271 SCIP_Real tmp;
15272 assert(!SCIPisInfinity(scip, -lhs));
15273
15274 for( i = 0; i < nlocvars; ++i )
15275 vals[i] *= -1;
15276 tmp = rhs;
15277 rhs = -lhs;
15278 lhs = -tmp;
15279 }
15280
15282 cons, lhs, rhs, success) );
15283
15284 SCIPfreeBufferArray(scip, &vals);
15286
15287 return SCIP_OKAY;
15288}
15289
15290/*
15291 * Callback methods of constraint handler
15292 */
15293
15294/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15295static
15296SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15297{ /*lint --e{715}*/
15298 assert(scip != NULL);
15299 assert(conshdlr != NULL);
15300 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15301
15302 /* call inclusion method of constraint handler */
15304
15305 *valid = TRUE;
15306
15307 return SCIP_OKAY;
15308}
15309
15310/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15311static
15312SCIP_DECL_CONSFREE(consFreeLinear)
15313{ /*lint --e{715}*/
15314 SCIP_CONSHDLRDATA* conshdlrdata;
15315
15316 assert(scip != NULL);
15317 assert(conshdlr != NULL);
15318 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15319
15320 /* free constraint handler data */
15321 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15322 assert(conshdlrdata != NULL);
15323
15324 conshdlrdataFree(scip, &conshdlrdata);
15325
15326 SCIPconshdlrSetData(conshdlr, NULL);
15327
15328 return SCIP_OKAY;
15329}
15330
15331
15332/** initialization method of constraint handler (called after problem was transformed) */
15333static
15334SCIP_DECL_CONSINIT(consInitLinear)
15335{
15336 SCIP_CONSHDLRDATA* conshdlrdata;
15337 int c;
15338
15339 assert(scip != NULL);
15340
15341 /* check for event handler */
15342 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15343 assert(conshdlrdata != NULL);
15344 assert(conshdlrdata->eventhdlr != NULL);
15345 assert(nconss == 0 || conss != NULL);
15346
15347 conshdlrdata->naddconss = 0;
15348
15349 /* catch events for the constraints */
15350 for( c = 0; c < nconss; ++c )
15351 {
15352 /* catch all events */
15353 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15354 }
15355
15356 return SCIP_OKAY;
15357}
15358
15359
15360/** deinitialization method of constraint handler (called before transformed problem is freed) */
15361static
15362SCIP_DECL_CONSEXIT(consExitLinear)
15363{
15364 SCIP_CONSHDLRDATA* conshdlrdata;
15365 int c;
15366
15367 assert(scip != NULL);
15368
15369 /* check for event handler */
15370 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15371 assert(conshdlrdata != NULL);
15372 assert(conshdlrdata->eventhdlr != NULL);
15373
15374 /* drop events for the constraints */
15375 for( c = nconss - 1; c >= 0; --c )
15376 {
15377 SCIP_CONSDATA* consdata;
15378
15379 consdata = SCIPconsGetData(conss[c]);
15380 assert(consdata != NULL);
15381
15382 if( consdata->eventdata != NULL )
15383 {
15384 /* drop all events */
15385 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15386 assert(consdata->eventdata == NULL);
15387 }
15388 }
15389
15390 return SCIP_OKAY;
15391}
15392
15393/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15394static
15395SCIP_Bool isRangedRow(
15396 SCIP* scip, /**< SCIP data structure */
15397 SCIP_Real lhs, /**< left hand side */
15398 SCIP_Real rhs /**< right hand side */
15399 )
15400{
15401 assert(scip != NULL);
15402
15403 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15404}
15405
15406/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15407static
15409 SCIP* scip, /**< SCIP data structure */
15410 SCIP_Real x /**< value */
15411 )
15412{
15413 assert(scip != NULL);
15414
15415 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15416}
15417
15418/** performs linear constraint type classification as used for MIPLIB
15419 *
15420 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15421 *
15422 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15423 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15424 * Similarly, if specialized constraints were created through the API, these are currently not present.
15425 */
15427 SCIP* scip, /**< SCIP data structure */
15428 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15429 )
15430{
15431 int c;
15432 SCIP_CONSHDLR* conshdlr;
15433 SCIP_CONS** conss;
15434 int nconss;
15435
15436 assert(scip != NULL);
15437 assert(linconsstats != NULL);
15438 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15439 assert(conshdlr != NULL);
15440
15442 {
15443 conss = SCIPgetConss(scip);
15444 nconss = SCIPgetNConss(scip);
15445 }
15446 else
15447 {
15448 conss = SCIPconshdlrGetConss(conshdlr);
15449 nconss = SCIPconshdlrGetNConss(conshdlr);
15450 }
15451
15452 /* reset linear constraint type classification */
15453 SCIPlinConsStatsReset(linconsstats);
15454
15455 /* loop through all constraints */
15456 for( c = 0; c < nconss; c++ )
15457 {
15458 SCIP_CONS* cons;
15459 SCIP_CONSDATA* consdata;
15460 SCIP_Real lhs;
15461 SCIP_Real rhs;
15462 int i;
15463
15464 /* get constraint */
15465 cons = conss[c];
15466 assert(cons != NULL);
15467
15468 /* skip constraints that are not handled by the constraint handler */
15469 if( SCIPconsGetHdlr(cons) != conshdlr )
15470 continue;
15471
15472 /* get constraint data */
15473 consdata = SCIPconsGetData(cons);
15474 assert(consdata != NULL);
15475 rhs = consdata->rhs;
15476 lhs = consdata->lhs;
15477
15478 /* merge multiples and delete variables with zero coefficient */
15479 SCIP_CALL( mergeMultiples(scip, cons) );
15480 for( i = 0; i < consdata->nvars; i++ )
15481 {
15482 assert(!SCIPisZero(scip, consdata->vals[i]));
15483 }
15484
15485 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15486 if( consdata->nvars == 0 )
15487 {
15488 SCIPdebugMsg(scip, "classified as EMPTY: ");
15491
15492 continue;
15493 }
15494
15495 /* is constraint of type SCIP_CONSTYPE_FREE? */
15496 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15497 {
15498 SCIPdebugMsg(scip, "classified as FREE: ");
15501
15502 continue;
15503 }
15504
15505 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15506 if( consdata->nvars == 1 )
15507 {
15508 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15511
15512 continue;
15513 }
15514
15515 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15516 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15517 {
15518 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15521
15522 continue;
15523 }
15524
15525 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15526 if( consdata->nvars == 2 )
15527 {
15528 SCIP_LINCONSTYPE constype;
15529
15530 /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15531 if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15532 && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15533 {
15534 constype = SCIP_LINCONSTYPE_PRECEDENCE;
15535 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15536 }
15537 else
15538 {
15539 constype = SCIP_LINCONSTYPE_VARBOUND;
15540 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15541 }
15543
15544 SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15545
15546 continue;
15547 }
15548
15549 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15550 {
15551 SCIP_Real scale;
15552 SCIP_Real b;
15553 SCIP_Bool unmatched;
15554 int nnegbinvars;
15555
15556 unmatched = FALSE;
15557 nnegbinvars = 0;
15558
15559 scale = REALABS(consdata->vals[0]);
15560
15561 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15562 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15563 {
15564 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15565 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15566 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15567 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15568
15569 if( consdata->vals[i] < 0.0 )
15570 nnegbinvars++;
15571 }
15572
15573 if( !unmatched )
15574 {
15575 if( SCIPisEQ(scip, lhs, rhs) )
15576 {
15577 b = rhs/scale + nnegbinvars;
15578 if( SCIPisEQ(scip, 1.0, b) )
15579 {
15580 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15583
15584 continue;
15585 }
15586 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15587 {
15588 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15591
15592 continue;
15593 }
15594 }
15595
15596 /* compute right hand side divided by scale */
15597 if( !SCIPisInfinity(scip, rhs) )
15598 b = rhs/scale + nnegbinvars;
15599 else
15600 b = SCIPinfinity(scip);
15601
15602 if( SCIPisEQ(scip, 1.0, b) )
15603 {
15604 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15607
15608 /* relax right hand side to prevent further classifications */
15609 rhs = SCIPinfinity(scip);
15610 }
15611 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15612 {
15613 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15615
15617
15618 /* relax right hand side to prevent further classifications */
15619 rhs = SCIPinfinity(scip);
15620 }
15621
15622 if( !SCIPisInfinity(scip, lhs) )
15623 b = lhs/scale + nnegbinvars;
15624 else
15625 b = SCIPinfinity(scip);
15626
15627 if( SCIPisEQ(scip, 1.0, b) )
15628 {
15629 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15632
15633 /* relax left hand side to prevent further classifications */
15634 lhs = -SCIPinfinity(scip);
15635 }
15636
15637 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15638 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15639 continue;
15640 }
15641 }
15642
15643 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15644 /* @todo If coefficients or rhs are not integral, we currently do not check
15645 * if the constraint could be scaled (finitely), such that they are.
15646 */
15647 {
15648 SCIP_Real b;
15649 SCIP_Bool unmatched;
15650
15651 b = rhs;
15652 unmatched = FALSE;
15653 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15654 {
15655 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15656 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15657 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15658 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15659
15660 if( SCIPisNegative(scip, consdata->vals[i]) )
15661 b -= consdata->vals[i];
15662 }
15663 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15664
15665 if( !unmatched )
15666 {
15667 if( SCIPisEQ(scip, lhs, rhs) )
15668 {
15669 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15671
15673
15674 continue;
15675 }
15676 else
15677 {
15678 SCIP_Bool matched;
15679
15680 matched = FALSE;
15681 for( i = 0; i < consdata->nvars && !matched; i++ )
15682 {
15683 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15684 }
15685
15686 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15689 }
15690
15691 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15692 if( SCIPisInfinity(scip, -lhs) )
15693 continue;
15694 else
15695 rhs = SCIPinfinity(scip);
15696 }
15697 }
15698
15699 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15700 {
15701 SCIP_Real b;
15702 SCIP_Bool unmatched;
15703
15704 unmatched = FALSE;
15705
15706 b = rhs;
15707 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15708
15709 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15710 {
15711 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15712 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15713 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15714 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15715 }
15716
15717 if( !unmatched )
15718 {
15719 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15722
15723 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15724 if( SCIPisInfinity(scip, -lhs) )
15725 continue;
15726 else
15727 rhs = SCIPinfinity(scip);
15728 }
15729 }
15730
15731 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15732 {
15733 SCIP_Bool unmatched;
15734
15735 unmatched = FALSE;
15736 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15737 {
15738 if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15739 && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15740 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15741 unmatched = TRUE;
15742 }
15743
15744 if( !unmatched )
15745 {
15746 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15749
15750 continue;
15751 }
15752 }
15753
15754 /* no special structure detected */
15755 SCIPdebugMsg(scip, "classified as GENERAL: ");
15757 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15758 }
15759
15760 return SCIP_OKAY;
15761}
15762
15763
15764/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15765static
15766SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15767{ /*lint --e{715}*/
15768 int c;
15769#ifdef SCIP_STATISTIC
15770 SCIP_CONSHDLRDATA* conshdlrdata;
15771 int ngoodconss;
15772 int nallconss;
15773#endif
15774
15775 /* delete all linear constraints that were upgraded to a more specific constraint type;
15776 * make sure, only active variables remain in the remaining constraints
15777 */
15778 assert(scip != NULL);
15779
15780#ifdef SCIP_STATISTIC
15781 /* count number of well behaved linear constraints */
15782 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15783 assert(conshdlrdata != NULL);
15784
15785 ngoodconss = 0;
15786 nallconss = 0;
15787
15788 for( c = 0; c < nconss; ++c )
15789 {
15790 SCIP_CONSDATA* consdata;
15791
15792 if( SCIPconsIsDeleted(conss[c]) )
15793 continue;
15794
15795 consdata = SCIPconsGetData(conss[c]);
15796 assert(consdata != NULL);
15797
15798 if( consdata->upgraded )
15799 continue;
15800
15801 nallconss++;
15802
15804
15805 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15806 ngoodconss++;
15807 }
15808 if( nallconss )
15809 {
15810 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15811 }
15812#endif
15813
15814 for( c = 0; c < nconss; ++c )
15815 {
15816 SCIP_CONSDATA* consdata;
15817
15818 if( SCIPconsIsDeleted(conss[c]) )
15819 continue;
15820
15821 consdata = SCIPconsGetData(conss[c]);
15822 assert(consdata != NULL);
15823
15824 if( consdata->upgraded )
15825 {
15826 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15827 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15828 */
15829 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15830 }
15831 else
15832 {
15833 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15834 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15835 }
15836 }
15837
15838 return SCIP_OKAY;
15839}
15840
15841/** solving process initialization method of constraint handler */
15842static
15843SCIP_DECL_CONSINITSOL(consInitsolLinear)
15844{ /*lint --e{715}*/
15845 /* add nlrow representation to NLP, if NLP had been constructed */
15847 {
15848 int c;
15849 for( c = 0; c < nconss; ++c )
15850 {
15851 SCIP_CALL( addNlrow(scip, conss[c]) );
15852 }
15853 }
15854
15855 return SCIP_OKAY;
15856}
15857
15858/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15859static
15860SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15861{ /*lint --e{715}*/
15862 int c;
15863
15864 assert(scip != NULL);
15865
15866 /* release the rows and nlrows of all constraints */
15867 for( c = 0; c < nconss; ++c )
15868 {
15869 SCIP_CONSDATA* consdata;
15870
15871 consdata = SCIPconsGetData(conss[c]);
15872 assert(consdata != NULL);
15873
15874 if( consdata->row != NULL )
15875 {
15876 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15877 }
15878
15879 if( consdata->nlrow != NULL )
15880 {
15881 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15882 }
15883 }
15884
15885 /* if this is a restart, convert cutpool rows into linear constraints */
15886 if( restart )
15887 {
15888 int ncutsadded;
15889
15890 ncutsadded = 0;
15891
15892 /* create out of all active cuts in cutpool linear constraints */
15893 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15894
15895 if( ncutsadded > 0 )
15896 {
15898 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15899 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15900 * line correctly
15901 */
15903 }
15904 }
15905
15906 return SCIP_OKAY;
15907}
15908
15909
15910/** constraint activation notification method of constraint handler */
15911static
15912SCIP_DECL_CONSACTIVE(consActiveLinear)
15913{ /*lint --e{715}*/
15914 assert(cons != NULL);
15915
15917 {
15918 SCIP_CALL( addNlrow(scip, cons) );
15919 }
15920
15921 return SCIP_OKAY;
15922}
15923
15924/** constraint deactivation notification method of constraint handler */
15925static
15926SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15927{ /*lint --e{715}*/
15928 SCIP_CONSDATA* consdata;
15929
15930 assert(scip != NULL);
15931 assert(conshdlr != NULL);
15932 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15933 assert(cons != NULL );
15934
15935 /* get constraint data */
15936 consdata = SCIPconsGetData(cons);
15937 assert(consdata != NULL);
15938
15939 if( SCIPconsIsDeleted(cons) )
15940 {
15941 SCIP_CONSHDLRDATA* conshdlrdata;
15942
15943 /* check for event handler */
15944 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15945 assert(conshdlrdata != NULL);
15946 assert(conshdlrdata->eventhdlr != NULL);
15947
15948 /* free event data */
15949 if( consdata->eventdata != NULL )
15950 {
15951 /* drop bound change events of variables */
15952 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15953 }
15954 assert(consdata->eventdata == NULL);
15955 }
15956
15957 /* remove row from NLP, if still in solving
15958 * if we are in exitsolve, the whole NLP will be freed anyway
15959 */
15960 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15961 {
15962 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15963 }
15964
15965 return SCIP_OKAY;
15966}
15967
15968
15969/** frees specific constraint data */
15970static
15971SCIP_DECL_CONSDELETE(consDeleteLinear)
15972{ /*lint --e{715}*/
15973 assert(scip != NULL);
15974 assert(conshdlr != NULL);
15975 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15976
15977 if( (*consdata)->eventdata != NULL )
15978 {
15979 SCIP_CONSHDLRDATA* conshdlrdata;
15980
15981 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15982 assert(conshdlrdata != NULL);
15983
15984 /* drop all events */
15985 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15986 assert((*consdata)->eventdata == NULL);
15987 }
15988
15989 /* free linear constraint */
15990 SCIP_CALL( consdataFree(scip, consdata) );
15991
15992 return SCIP_OKAY;
15993}
15994
15995
15996/** transforms constraint data into data belonging to the transformed problem */
15997static
15998SCIP_DECL_CONSTRANS(consTransLinear)
15999{ /*lint --e{715}*/
16000 SCIP_CONSDATA* sourcedata;
16001 SCIP_CONSDATA* targetdata;
16002
16003 /*debugMsg(scip, "Trans method of linear constraints\n");*/
16004
16005 assert(scip != NULL);
16006 assert(conshdlr != NULL);
16007 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16009 assert(sourcecons != NULL);
16010 assert(targetcons != NULL);
16011
16012 sourcedata = SCIPconsGetData(sourcecons);
16013 assert(sourcedata != NULL);
16014 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
16015
16016 /* create linear constraint data for target constraint */
16017 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
16018
16019#ifndef NDEBUG
16020 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
16021 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
16022 {
16023 int n;
16024 for(n = targetdata->nvars - 1; n >= 0; --n )
16025 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
16026 }
16027#endif
16028
16029 /* create target constraint */
16030 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
16031 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
16032 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
16033 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
16034 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
16035
16036 return SCIP_OKAY;
16037}
16038
16039
16040/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
16041static
16042SCIP_DECL_CONSINITLP(consInitlpLinear)
16043{ /*lint --e{715}*/
16044 int c;
16045
16046 assert(scip != NULL);
16047 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16048
16049 *infeasible = FALSE;
16050
16051 for( c = 0; c < nconss && !(*infeasible); ++c )
16052 {
16053 assert(SCIPconsIsInitial(conss[c]));
16054 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
16055 }
16056
16057 return SCIP_OKAY;
16058}
16059
16060
16061/** separation method of constraint handler for LP solutions */
16062static
16063SCIP_DECL_CONSSEPALP(consSepalpLinear)
16064{ /*lint --e{715}*/
16065 SCIP_CONSHDLRDATA* conshdlrdata;
16066 SCIP_Real loclowerbound;
16067 SCIP_Real glblowerbound;
16068 SCIP_Real cutoffbound;
16069 SCIP_Real maxbound;
16070 SCIP_Bool separatecards;
16071 SCIP_Bool cutoff;
16072 int c;
16073 int depth;
16074 int nrounds;
16075 int maxsepacuts;
16076 int ncuts;
16077
16078 assert(scip != NULL);
16079 assert(conshdlr != NULL);
16080 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16081 assert(result != NULL);
16082
16083 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16084 assert(conshdlrdata != NULL);
16086 nrounds = SCIPgetNSepaRounds(scip);
16087
16088 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16089
16091
16092 /* only call the separator a given number of times at each node */
16093 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16094 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16095 return SCIP_OKAY;
16096
16097 /* get the maximal number of cuts allowed in a separation round */
16098 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16099
16100 /* check if we want to produce knapsack cardinality cuts at this node */
16101 loclowerbound = SCIPgetLocalLowerbound(scip);
16102 glblowerbound = SCIPgetLowerbound(scip);
16103 cutoffbound = SCIPgetCutoffbound(scip);
16104 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16105 separatecards = SCIPisLE(scip, loclowerbound, maxbound);
16106 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
16107
16109 ncuts = 0;
16110 cutoff = FALSE;
16111
16112 /* check all useful linear constraints for feasibility */
16113 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16114 {
16115 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16116 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16117 }
16118
16119 /* adjust return value */
16120 if( cutoff )
16122 else if( ncuts > 0 )
16124
16125 /* combine linear constraints to get more cuts */
16126 /**@todo further cuts of linear constraints */
16127
16128 return SCIP_OKAY;
16129}
16130
16131
16132/** separation method of constraint handler for arbitrary primal solutions */
16133static
16134SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16135{ /*lint --e{715}*/
16136 SCIP_CONSHDLRDATA* conshdlrdata;
16137 int c;
16138 int depth;
16139 int nrounds;
16140 int maxsepacuts;
16141 int ncuts;
16142 SCIP_Bool cutoff;
16143
16144 assert(scip != NULL);
16145 assert(conshdlr != NULL);
16146 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16147 assert(result != NULL);
16148
16149 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16150 assert(conshdlrdata != NULL);
16152 nrounds = SCIPgetNSepaRounds(scip);
16153
16154 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16155
16157
16158 /* only call the separator a given number of times at each node */
16159 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16160 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16161 return SCIP_OKAY;
16162
16163 /* get the maximal number of cuts allowed in a separation round */
16164 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16165
16167 ncuts = 0;
16168 cutoff = FALSE;
16169
16170 /* check all useful linear constraints for feasibility */
16171 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16172 {
16173 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16174 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16175 }
16176
16177 /* adjust return value */
16178 if( cutoff )
16180 else if( ncuts > 0 )
16182
16183 /* combine linear constraints to get more cuts */
16184 /**@todo further cuts of linear constraints */
16185
16186 return SCIP_OKAY;
16187}
16188
16189
16190/** constraint enforcing method of constraint handler for LP solutions */
16191static
16192SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16193{ /*lint --e{715}*/
16194 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16195
16196 return SCIP_OKAY;
16197}
16198
16199/** constraint enforcing method of constraint handler for relaxation solutions */
16200static
16201SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16202{ /*lint --e{715}*/
16203 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16204
16205 return SCIP_OKAY;
16206}
16207
16208/** constraint enforcing method of constraint handler for pseudo solutions */
16209static
16210SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16211{ /*lint --e{715}*/
16212 SCIP_CONSHDLRDATA* conshdlrdata;
16213 SCIP_Bool checkrelmaxabs;
16214 SCIP_Bool violated;
16215 int c;
16216
16217 assert(scip != NULL);
16218 assert(conshdlr != NULL);
16219 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16220 assert(result != NULL);
16221
16222 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16223 assert(conshdlrdata != NULL);
16224
16225 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16226
16227 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16228
16229 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16230 if( objinfeasible )
16231 {
16232 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16233
16235 return SCIP_OKAY;
16236 }
16237
16238 /* check all linear constraints for feasibility */
16239 violated = FALSE;
16240 for( c = 0; c < nconss && !violated; ++c )
16241 {
16242 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16243 }
16244
16245 if( violated )
16247 else
16249
16250 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16251
16252 return SCIP_OKAY;
16253}
16254
16255
16256/** feasibility check method of constraint handler for integral solutions */
16257static
16258SCIP_DECL_CONSCHECK(consCheckLinear)
16259{ /*lint --e{715}*/
16260 SCIP_CONSHDLRDATA* conshdlrdata;
16261 SCIP_Bool checkrelmaxabs;
16262 int c;
16263
16264 assert(scip != NULL);
16265 assert(conshdlr != NULL);
16266 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16267 assert(result != NULL);
16268
16270
16271 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16272 assert(conshdlrdata != NULL);
16273
16274 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16275
16276 /*debugMsg(scip, "Check method of linear constraints\n");*/
16277
16278 /* check all linear constraints for feasibility */
16279 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16280 {
16281 SCIP_Bool violated = FALSE;
16282 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16283
16284 if( violated )
16285 {
16287
16288 if( printreason )
16289 {
16290 SCIP_CONSDATA* consdata;
16291 SCIP_Real activity;
16292
16293 consdata = SCIPconsGetData(conss[c]);
16294 assert( consdata != NULL);
16295
16296 activity = consdataGetActivity(scip, consdata, sol);
16297
16298 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16299 SCIPinfoMessage(scip, NULL, ";\n");
16300
16301 if( activity == SCIP_INVALID ) /*lint !e777*/
16302 SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16303 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16304 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16305 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16306 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16307 }
16308 }
16309 }
16310
16311 return SCIP_OKAY;
16312}
16313
16314
16315/** domain propagation method of constraint handler */
16316static
16317SCIP_DECL_CONSPROP(consPropLinear)
16318{ /*lint --e{715}*/
16319 SCIP_CONSHDLRDATA* conshdlrdata;
16320 SCIP_Bool rangedrowpropagation = FALSE;
16321 SCIP_Bool tightenbounds;
16322 SCIP_Bool cutoff;
16323
16324 int nchgbds;
16325 int i;
16326
16327 assert(scip != NULL);
16328 assert(conshdlr != NULL);
16329 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16330 assert(result != NULL);
16331
16332 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16333 assert(conshdlrdata != NULL);
16334
16335 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16336
16337 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16338 if( SCIPinProbing(scip) )
16339 tightenbounds = TRUE;
16340 else
16341 {
16342 int depth;
16343 int propfreq;
16344 int tightenboundsfreq;
16345 int rangedrowfreq;
16346
16348 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16349 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16350 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16351 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16352
16353 /* check if we want to do ranged row propagation */
16354 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16355 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16356 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16357 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16358 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16359 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16360 }
16361
16362 cutoff = FALSE;
16363 nchgbds = 0;
16364
16365 /* process constraints marked for propagation */
16366 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16367 {
16369 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16370 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16371 }
16372
16373 /* adjust result code */
16374 if( cutoff )
16376 else if( nchgbds > 0 )
16378 else
16380
16381 return SCIP_OKAY;
16382}
16383
16384
16385#define MAXCONSPRESOLROUNDS 10
16386/** presolving method of constraint handler */
16387static
16388SCIP_DECL_CONSPRESOL(consPresolLinear)
16389{ /*lint --e{715}*/
16390 SCIP_CONSHDLRDATA* conshdlrdata;
16391 SCIP_CONS* cons;
16392 SCIP_CONSDATA* consdata;
16393 SCIP_Real minactivity;
16394 SCIP_Real maxactivity;
16395 SCIP_Bool isminacttight;
16396 SCIP_Bool ismaxacttight;
16397 SCIP_Bool isminsettoinfinity;
16398 SCIP_Bool ismaxsettoinfinity;
16399 SCIP_Bool cutoff;
16400 int oldnfixedvars;
16401 int oldnaggrvars;
16402 int oldnchgbds;
16403 int oldndelconss;
16404 int oldnupgdconss;
16405 int oldnchgcoefs;
16406 int oldnchgsides;
16407 int firstchange;
16408 int firstupgradetry;
16409 int c;
16410
16411 assert(scip != NULL);
16412 assert(conshdlr != NULL);
16413 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16414 assert(result != NULL);
16415
16416 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16417
16418 /* remember old preprocessing counters */
16419 cutoff = FALSE;
16420 oldnfixedvars = *nfixedvars;
16421 oldnaggrvars = *naggrvars;
16422 oldnchgbds = *nchgbds;
16423 oldndelconss = *ndelconss;
16424 oldnupgdconss = *nupgdconss;
16425 oldnchgcoefs = *nchgcoefs;
16426 oldnchgsides = *nchgsides;
16427
16428 /* get constraint handler data */
16429 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16430 assert(conshdlrdata != NULL);
16431
16432 /* process single constraints */
16433 firstchange = INT_MAX;
16434 firstupgradetry = INT_MAX;
16435 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16436 {
16437 int npresolrounds;
16438 SCIP_Bool infeasible;
16439
16440 infeasible = FALSE;
16441
16442 cons = conss[c];
16443 assert(SCIPconsIsActive(cons));
16444 consdata = SCIPconsGetData(cons);
16445 assert(consdata != NULL);
16446
16447 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16448 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16449 {
16450 consdata->lhs = consdata->rhs;
16451 assert(consdata->row == NULL);
16452 }
16453
16454 if( consdata->eventdata == NULL )
16455 {
16456 /* catch bound change events of variables */
16457 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16458 assert(consdata->eventdata != NULL);
16459 }
16460
16461 /* constraint should not be already presolved in the initial round */
16462 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16463 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16464 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16465 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16466
16467 /* incorporate fixings and aggregations in constraint */
16468 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16469
16470 if( infeasible )
16471 {
16472 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16473 cutoff = TRUE;
16474 break;
16475 }
16476
16477 assert(consdata->removedfixings);
16478
16479 /* we can only presolve linear constraints, that are not modifiable */
16480 if( SCIPconsIsModifiable(cons) )
16481 continue;
16482
16483 /* remember the first changed constraint to begin the next aggregation round with */
16484 if( firstchange == INT_MAX && consdata->changed )
16485 firstchange = c;
16486
16487 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16488 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16489 firstupgradetry = c;
16490
16491 /* check, if constraint is already preprocessed */
16492 if( consdata->presolved )
16493 continue;
16494
16495 assert(SCIPconsIsActive(cons));
16496
16497 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16499
16500 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16501 * to avoid nearly infinite cycling due to very small bound changes)
16502 */
16503 npresolrounds = 0;
16504 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16505 {
16506 assert(!cutoff);
16507 npresolrounds++;
16508
16509 /* mark constraint being presolved and propagated */
16510 consdata->presolved = TRUE;
16512
16513 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16514
16515 if( infeasible )
16516 {
16517 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16518 cutoff = TRUE;
16519 break;
16520 }
16521
16522 /* tighten left and right hand side due to integrality */
16523 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16524
16525 if( infeasible )
16526 {
16527 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16528 cutoff = TRUE;
16529 break;
16530 }
16531
16532 /* check bounds */
16533 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16534 {
16535 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16536 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16537 cutoff = TRUE;
16538 break;
16539 }
16540
16541 /* tighten variable's bounds */
16542 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16543 if( cutoff )
16544 break;
16545
16546 /* check for fixed variables */
16547 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16548 if( cutoff )
16549 break;
16550
16551 /* check constraint for infeasibility and redundancy */
16552 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
16553 &isminsettoinfinity, &ismaxsettoinfinity);
16554 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16555 {
16556 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16557 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16558 cutoff = TRUE;
16559 break;
16560 }
16561 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16562 {
16563 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16564 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16565 SCIP_CALL( SCIPdelCons(scip, cons) );
16566 assert(!SCIPconsIsActive(cons));
16567
16568 if( !consdata->upgraded )
16569 (*ndelconss)++;
16570 break;
16571 }
16572 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16573 {
16574 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16575 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16576 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16577 if( !consdata->upgraded )
16578 (*nchgsides)++;
16579 }
16580 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16581 {
16582 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16583 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16585 if( !consdata->upgraded )
16586 (*nchgsides)++;
16587 }
16588
16589 /* handle empty constraint */
16590 if( consdata->nvars == 0 )
16591 {
16592 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16593 {
16594 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16595 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16596 cutoff = TRUE;
16597 }
16598 else
16599 {
16600 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16601 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16602 SCIP_CALL( SCIPdelCons(scip, cons) );
16603 assert(!SCIPconsIsActive(cons));
16604
16605 if( !consdata->upgraded )
16606 (*ndelconss)++;
16607 }
16608 break;
16609 }
16610
16611 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16612 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16613
16614 /* try to simplify inequalities */
16615 if( conshdlrdata->simplifyinequalities )
16616 {
16617 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16618
16619 if( cutoff )
16620 break;
16621 }
16622
16623 /* aggregation variable in equations */
16624 if( conshdlrdata->aggregatevariables )
16625 {
16626 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16627 if( cutoff )
16628 break;
16629 }
16630 }
16631
16632 if( !cutoff && !SCIPisStopped(scip) )
16633 {
16634 /* perform ranged row propagation */
16635 if( conshdlrdata->rangedrowpropagation )
16636 {
16637 int lastnfixedvars;
16638
16639 lastnfixedvars = *nfixedvars;
16640
16641 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16642 if( !cutoff )
16643 {
16644 if( lastnfixedvars < *nfixedvars )
16645 {
16646 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16647 }
16648 }
16649 }
16650
16651 /* extract cliques from constraint */
16652 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16653 {
16654 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16655 nfixedvars, nchgbds, &cutoff) );
16656
16657 /* check if the constraint got redundant or infeasible */
16658 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16659 {
16660 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16661 {
16662 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16663 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16664 cutoff = TRUE;
16665 }
16666 else
16667 {
16668 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16669 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16670 SCIP_CALL( SCIPdelCons(scip, cons) );
16671 assert(!SCIPconsIsActive(cons));
16672
16673 if( !consdata->upgraded )
16674 (*ndelconss)++;
16675 }
16676 }
16677 }
16678
16679 /* convert special equalities */
16680 if( !cutoff && SCIPconsIsActive(cons) )
16681 {
16682 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16683 }
16684
16685 /* apply dual presolving for variables that appear in only one constraint */
16686 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16687 {
16688 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16689 }
16690
16691 /* check if an inequality is parallel to the objective function */
16692 if( !cutoff && SCIPconsIsActive(cons) )
16693 {
16694 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16695 }
16696
16697 /* remember the first changed constraint to begin the next aggregation round with */
16698 if( firstchange == INT_MAX && consdata->changed )
16699 firstchange = c;
16700
16701 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16702 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16703 firstupgradetry = c;
16704 }
16705
16706 /* singleton column stuffing */
16707 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16708 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16709 {
16710 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16711 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16712
16713 /* handle empty constraint */
16714 if( consdata->nvars == 0 )
16715 {
16716 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16717 {
16718 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16719 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16720 cutoff = TRUE;
16721 }
16722 else
16723 {
16724 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16725 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16726 SCIP_CALL( SCIPdelCons(scip, cons) );
16727 assert(!SCIPconsIsActive(cons));
16728
16729 if( !consdata->upgraded )
16730 (*ndelconss)++;
16731 }
16732 break;
16733 }
16734 }
16735 }
16736
16737 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16738 * only apply this expensive procedure in exhaustive presolving timing
16739 */
16740 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16741 {
16742 assert(firstchange >= 0);
16743
16744 if( firstchange < nconss && conshdlrdata->presolusehashing )
16745 {
16746 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16747 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16748 ndelconss, nchgsides) );
16749 }
16750
16751 if( firstchange < nconss && conshdlrdata->presolpairwise )
16752 {
16753 SCIP_CONS** usefulconss;
16754 int nusefulconss;
16755 int firstchangenew;
16756 SCIP_Longint npaircomparisons;
16757
16758 npaircomparisons = 0;
16759 oldndelconss = *ndelconss;
16760 oldnchgsides = *nchgsides;
16761 oldnchgcoefs = *nchgcoefs;
16762
16763 /* allocate temporary memory */
16764 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16765
16766 nusefulconss = 0;
16767 firstchangenew = -1;
16768 for( c = 0; c < nconss; ++c )
16769 {
16770 /* update firstchange */
16771 if( c == firstchange )
16772 firstchangenew = nusefulconss;
16773
16774 /* ignore inactive and modifiable constraints */
16775 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16776 continue;
16777
16778 usefulconss[nusefulconss] = conss[c];
16779 ++nusefulconss;
16780 }
16781 firstchange = firstchangenew;
16782 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16783
16784 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16785 {
16786 /* constraint has become inactive or modifiable during pairwise presolving */
16787 if( usefulconss[c] == NULL )
16788 continue;
16789
16790 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16791
16792 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16793 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16794 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16795
16796 if( npaircomparisons > conshdlrdata->nmincomparisons )
16797 {
16798 assert(npaircomparisons > 0);
16799 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16800 break;
16801 oldndelconss = *ndelconss;
16802 oldnchgsides = *nchgsides;
16803 oldnchgcoefs = *nchgcoefs;
16804 npaircomparisons = 0;
16805 }
16806 }
16807 /* free temporary memory */
16808 SCIPfreeBufferArray(scip, &usefulconss);
16809 }
16810 }
16811
16812 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16813 * in linear constraints and we therefore have full information about it
16814 */
16815 if( !cutoff && firstupgradetry < nconss
16816 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16817 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16818 )
16819 {
16820 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16821 {
16822 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16823 }
16824 }
16825
16826 /* try to upgrade constraints into a more specific constraint type;
16827 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16828 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16829 */
16830 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16831 {
16832 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16833 {
16834 cons = conss[c];
16835
16836 /* don't upgrade modifiable constraints */
16837 if( SCIPconsIsModifiable(cons) )
16838 continue;
16839
16840 consdata = SCIPconsGetData(cons);
16841 assert(consdata != NULL);
16842
16843 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16844 if( consdata->upgradetried )
16845 continue;
16846 /* @todo force that upgrade will be performed later? */
16847 if( !consdata->presolved )
16848 continue;
16849
16850 consdata->upgradetried = TRUE;
16851 if( SCIPconsIsActive(cons) )
16852 {
16853 SCIP_CONS* upgdcons;
16854
16855 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16856 if( upgdcons != NULL )
16857 {
16858 /* add the upgraded constraint to the problem */
16859 SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16860 SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16861 (*nupgdconss)++;
16862
16863 /* mark the linear constraint being upgraded and to be removed after presolving;
16864 * don't delete it directly, because it may help to preprocess other linear constraints
16865 */
16866 assert(!consdata->upgraded);
16867 consdata->upgraded = TRUE;
16868
16869 /* delete upgraded inequalities immediately;
16870 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16871 */
16872 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16873 || !conshdlrdata->presolpairwise
16874 || (conshdlrdata->maxaggrnormscale == 0.0) )
16875 {
16876 SCIP_CALL( SCIPdelCons(scip, cons) );
16877 }
16878 }
16879 }
16880 }
16881 }
16882
16883 /* return the correct result code */
16884 if( cutoff )
16886 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16887 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16889 else
16891
16892 return SCIP_OKAY;
16893}
16894
16895
16896/** propagation conflict resolving method of constraint handler */
16897static
16898SCIP_DECL_CONSRESPROP(consRespropLinear)
16899{ /*lint --e{715}*/
16900 assert(scip != NULL);
16901 assert(cons != NULL);
16902 assert(result != NULL);
16903
16904 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16905
16906 return SCIP_OKAY;
16907}
16908
16909
16910/** variable rounding lock method of constraint handler */
16911static
16912SCIP_DECL_CONSLOCK(consLockLinear)
16913{ /*lint --e{715}*/
16914 SCIP_CONSDATA* consdata;
16915 SCIP_Bool haslhs;
16916 SCIP_Bool hasrhs;
16917 int i;
16918
16919 assert(scip != NULL);
16920 assert(cons != NULL);
16921 consdata = SCIPconsGetData(cons);
16922 assert(consdata != NULL);
16923
16924 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16925 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16926
16927 /* update rounding locks of every single variable */
16928 for( i = 0; i < consdata->nvars; ++i )
16929 {
16930 if( SCIPisPositive(scip, consdata->vals[i]) )
16931 {
16932 if( haslhs )
16933 {
16934 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16935 }
16936 if( hasrhs )
16937 {
16938 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16939 }
16940 }
16941 else
16942 {
16943 if( haslhs )
16944 {
16945 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16946 }
16947 if( hasrhs )
16948 {
16949 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16950 }
16951 }
16952 }
16953
16954 return SCIP_OKAY;
16955}
16956
16957
16958/** variable deletion method of constraint handler */
16959static
16960SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16961{
16962 assert(scip != NULL);
16963 assert(conshdlr != NULL);
16964 assert(conss != NULL || nconss == 0);
16965
16966 if( nconss > 0 )
16967 {
16968 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16969 }
16970
16971 return SCIP_OKAY;
16972}
16973
16974/** constraint display method of constraint handler */
16975static
16976SCIP_DECL_CONSPRINT(consPrintLinear)
16977{ /*lint --e{715}*/
16978 assert(scip != NULL);
16979 assert(conshdlr != NULL);
16980 assert(cons != NULL);
16981
16983
16984 return SCIP_OKAY;
16985}
16986
16987/** constraint copying method of constraint handler */
16988static
16989SCIP_DECL_CONSCOPY(consCopyLinear)
16990{ /*lint --e{715}*/
16991 SCIP_VAR** sourcevars;
16992 SCIP_Real* sourcecoefs;
16993 const char* consname;
16994 int nvars;
16995
16996 assert(scip != NULL);
16997 assert(sourcescip != NULL);
16998 assert(sourcecons != NULL);
16999
17000 /* get variables and coefficients of the source constraint */
17001 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
17002 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
17003 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
17004
17005 if( name != NULL )
17006 consname = name;
17007 else
17008 consname = SCIPconsGetName(sourcecons);
17009
17010 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
17011 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
17012 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
17013 assert(cons != NULL || *valid == FALSE);
17014
17015 /* @todo should also the checkabsolute flag of the constraint be copied? */
17016
17017 return SCIP_OKAY;
17018}
17019
17020/** find operators '<=', '==', '>=', [free] in input string and return those places
17021 *
17022 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
17023 */
17024static
17026 const char* str, /**< null terminated input string */
17027 char** firstoperator, /**< pointer to store the string starting at the first operator */
17028 char** secondoperator, /**< pointer to store the string starting at the second operator */
17029 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
17030 )
17031{
17032 char* curr;
17033
17034 assert(str != NULL);
17035 assert(firstoperator != NULL);
17036 assert(secondoperator != NULL);
17037
17038 *firstoperator = NULL;
17039 *secondoperator = NULL;
17040
17041 curr = (char*)str;
17042 *success = TRUE;
17043
17044 /* loop over the input string to find all operators */
17045 while( *curr && *success )
17046 {
17047 SCIP_Bool found = FALSE;
17048 int increment = 1;
17049
17050 /* try if we found a possible operator */
17051 switch( *curr )
17052 {
17053 case '<':
17054 case '=':
17055 case '>':
17056
17057 /* check if the two characters curr[0,1] form an operator together */
17058 if( curr[1] == '=' )
17059 {
17060 found = TRUE;
17061
17062 /* update increment to continue after this operator */
17063 increment = 2;
17064 }
17065 break;
17066 case '[':
17067 if( strncmp(curr, "[free]", 6) == 0 )
17068 {
17069 found = TRUE;
17070
17071 /* update increment to continue after this operator */
17072 increment = 6;
17073 }
17074 break;
17075 default:
17076 break;
17077 }
17078
17079 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
17080 if( found )
17081 {
17082 if( *firstoperator == NULL )
17083 {
17084 *firstoperator = curr;
17085 }
17086 else
17087 {
17088 if( *secondoperator != NULL )
17089 {
17090 SCIPerrorMessage("Found more than two operators in line %s\n", str);
17091 *success = FALSE;
17092 }
17093 else if( strncmp(*firstoperator, "<=", 2) != 0 )
17094 {
17095 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17096 *success = FALSE;
17097 }
17098 else if( strncmp(curr, "<=", 2) != 0 )
17099 {
17100 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17101 *success = FALSE;
17102 }
17103
17104 *secondoperator = curr;
17105 }
17106 }
17107
17108 curr += increment;
17109 }
17110
17111 /* check if we did find at least one operator */
17112 if( *success )
17113 {
17114 if( *firstoperator == NULL )
17115 {
17116 SCIPerrorMessage("Could not find any operator in line %s\n", str);
17117 *success = FALSE;
17118 }
17119 }
17120}
17121
17122/** constraint parsing method of constraint handler */
17123static
17124SCIP_DECL_CONSPARSE(consParseLinear)
17125{ /*lint --e{715}*/
17126 SCIP_VAR** vars;
17127 SCIP_Real* coefs;
17128 int nvars;
17129 int coefssize;
17130 int requsize;
17131 SCIP_Real lhs;
17132 SCIP_Real rhs;
17133 char* endptr;
17134 char* firstop;
17135 char* secondop;
17136 SCIP_Bool operatorsuccess;
17137 char* lhsstrptr;
17138 char* rhsstrptr;
17139 char* varstrptr;
17140
17141 assert(scip != NULL);
17142 assert(success != NULL);
17143 assert(str != NULL);
17144 assert(name != NULL);
17145 assert(cons != NULL);
17146
17147 /* set left and right hand side to their default values */
17148 lhs = -SCIPinfinity(scip);
17149 rhs = SCIPinfinity(scip);
17150
17151 (*success) = FALSE;
17152
17153 /* return of string empty */
17154 if( !*str )
17155 return SCIP_OKAY;
17156
17157 /* ignore whitespace */
17158 SCIP_CALL( SCIPskipSpace((char**)&str) );
17159
17160 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17161 * and the special word [free]
17162 */
17163 findOperators(str, &firstop, &secondop, &operatorsuccess);
17164
17165 /* if the grammar is not valid for parsing a linear constraint, return */
17166 if( ! operatorsuccess )
17167 return SCIP_OKAY;
17168
17169 varstrptr = (char *)str;
17170 lhsstrptr = rhsstrptr = NULL;
17171 assert(firstop != NULL);
17172
17173 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17174 switch( *firstop )
17175 {
17176 case '<':
17177 assert(firstop[1] == '=');
17178 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17179 if( secondop != NULL )
17180 {
17181 assert(secondop[0] == '<' && secondop[1] == '=');
17182 lhsstrptr = (char *)str;
17183 varstrptr = firstop + 2;
17184 rhsstrptr = secondop + 2;
17185 }
17186 else
17187 {
17188 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17189 lhsstrptr = NULL;
17190 varstrptr = (char *)str;
17191 rhsstrptr = firstop + 2;
17192 }
17193 break;
17194 case '>':
17195 assert(firstop[1] == '=');
17196 assert(secondop == NULL);
17197 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17198 lhsstrptr = firstop + 2;
17199 break;
17200 case '=':
17201 assert(firstop[1] == '=');
17202 assert(secondop == NULL);
17203 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17204 rhsstrptr = firstop + 2;
17205 lhsstrptr = firstop + 2;
17206 break;
17207 case '[':
17208 assert(strncmp(firstop, "[free]", 6) == 0);
17209 assert(secondop == NULL);
17210 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17211 break;
17212 default:
17213 /* it should not be possible that a different character appears in that position */
17214 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17215 return SCIP_READERROR;
17216 }
17217
17218 /* parse left hand side, if necessary */
17219 if( lhsstrptr != NULL )
17220 {
17221 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17222 {
17223 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17224 return SCIP_OKAY;
17225 }
17226
17227 /* in case of an equation, assign the left also to the right hand side */
17228 if( rhsstrptr == lhsstrptr )
17229 rhs = lhs;
17230 }
17231
17232 /* parse right hand side, if different from left hand side */
17233 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17234 {
17235 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17236 {
17237 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17238 return SCIP_OKAY;
17239 }
17240 }
17241
17242 /* initialize buffers for storing the variables and coefficients */
17243 coefssize = 100;
17244 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17245 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17246
17247 assert(varstrptr != NULL);
17248
17249 /* parse linear sum to get variables and coefficients */
17250 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17251
17252 if( *success && requsize > coefssize )
17253 {
17254 /* realloc buffers and try again */
17255 coefssize = requsize;
17256 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17257 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17258
17259 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17260 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17261 }
17262
17263 if( !*success )
17264 {
17265 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17266 }
17267 else
17268 {
17269 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17270 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17271 }
17272
17273 SCIPfreeBufferArray(scip, &coefs);
17275
17276 return SCIP_OKAY;
17277}
17278
17279
17280/** constraint method of constraint handler which returns the variables (if possible) */
17281static
17282SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17283{ /*lint --e{715}*/
17284 SCIP_CONSDATA* consdata;
17285
17286 consdata = SCIPconsGetData(cons);
17287 assert(consdata != NULL);
17288
17289 if( varssize < consdata->nvars )
17290 (*success) = FALSE;
17291 else
17292 {
17293 assert(vars != NULL);
17294
17295 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17296 (*success) = TRUE;
17297 }
17298
17299 return SCIP_OKAY;
17300}
17301
17302/**! [Callback for the number of variables]*/
17303/** constraint method of constraint handler which returns the number of variables (if possible) */
17304static
17305SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17306{ /*lint --e{715}*/
17307 SCIP_CONSDATA* consdata;
17308
17309 consdata = SCIPconsGetData(cons);
17310 assert(consdata != NULL);
17311
17312 (*nvars) = consdata->nvars;
17313 (*success) = TRUE;
17314
17315 return SCIP_OKAY;
17316}
17317/**! [Callback for the number of variables]*/
17318
17319/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17320static
17321SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17322{ /*lint --e{715}*/
17323 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17324
17325 return SCIP_OKAY;
17326}
17327
17328/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17329static
17330SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17331{ /*lint --e{715}*/
17332 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17333
17334 return SCIP_OKAY;
17335}
17336
17337/*
17338 * Callback methods of event handler
17339 */
17340
17341/** execution method of event handler */
17342static
17343SCIP_DECL_EVENTEXEC(eventExecLinear)
17344{ /*lint --e{715}*/
17345 SCIP_CONS* cons;
17346 SCIP_CONSDATA* consdata;
17347 SCIP_VAR* var;
17348 SCIP_EVENTTYPE eventtype;
17349
17350 assert(scip != NULL);
17351 assert(eventhdlr != NULL);
17352 assert(eventdata != NULL);
17353 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17354 assert(event != NULL);
17355
17356 cons = eventdata->cons;
17357 assert(cons != NULL);
17358 consdata = SCIPconsGetData(cons);
17359 assert(consdata != NULL);
17360
17361 /* we can skip events droped for deleted constraints */
17362 if( SCIPconsIsDeleted(cons) )
17363 return SCIP_OKAY;
17364
17365 eventtype = SCIPeventGetType(event);
17366 var = SCIPeventGetVar(event);
17367
17368 if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17369 {
17370 SCIP_Real oldbound;
17371 SCIP_Real newbound;
17372 SCIP_Real val;
17373 int varpos;
17374
17375 varpos = eventdata->varpos;
17376 assert(0 <= varpos && varpos < consdata->nvars);
17377 oldbound = SCIPeventGetOldbound(event);
17378 newbound = SCIPeventGetNewbound(event);
17379 assert(var != NULL);
17380 assert(consdata->vars[varpos] == var);
17381 val = consdata->vals[varpos];
17382
17383 /* we only need to update the activities if the constraint is active,
17384 * otherwise we mark them to be invalid
17385 */
17386 if( SCIPconsIsActive(cons) )
17387 {
17388 /* update the activity values */
17389 if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17390 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17391 else
17392 {
17393 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17394 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17395 }
17396 }
17397 else
17399
17400 consdata->presolved = FALSE;
17401 consdata->rangedrowpropagated = 0;
17402
17403 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17404 if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17405 {
17407
17408 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17409 if( consdata->maxactdeltavar == var )
17410 {
17411 consdata->maxactdelta = SCIP_INVALID;
17412 consdata->maxactdeltavar = NULL;
17413 }
17414
17415 /* check whether bound tightening might now be successful */
17416 if( consdata->boundstightened > 0)
17417 {
17418 switch( eventtype )
17419 {
17421 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17422 consdata->boundstightened = 0;
17423 break;
17425 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17426 consdata->boundstightened = 0;
17427 break;
17428 default:
17429 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17430 return SCIP_INVALIDDATA;
17431 }
17432 }
17433 }
17434 /* update maximal activity delta if a bound was relaxed */
17435 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17436 {
17437 SCIP_Real lb;
17438 SCIP_Real ub;
17439 SCIP_Real domain;
17440 SCIP_Real delta;
17441
17442 assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17443
17444 lb = SCIPvarGetLbLocal(var);
17445 ub = SCIPvarGetUbLocal(var);
17446
17447 domain = ub - lb;
17448 delta = REALABS(val) * domain;
17449
17450 if( delta > consdata->maxactdelta )
17451 {
17452 consdata->maxactdelta = delta;
17453 consdata->maxactdeltavar = var;
17454 }
17455 }
17456 }
17457 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17458 {
17459 /* we want to remove the fixed variable */
17460 consdata->presolved = FALSE;
17461 consdata->removedfixings = FALSE;
17462 consdata->rangedrowpropagated = 0;
17463
17464 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17465 if( consdata->maxactdeltavar == var )
17466 {
17467 consdata->maxactdelta = SCIP_INVALID;
17468 consdata->maxactdeltavar = NULL;
17469 }
17470 }
17471 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17472 {
17473 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17476 consdata->presolved = FALSE;
17477 }
17478 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17479 {
17480 SCIP_Real oldbound;
17481 SCIP_Real newbound;
17482 SCIP_Real val;
17483 int varpos;
17484
17485 varpos = eventdata->varpos;
17486 assert(0 <= varpos && varpos < consdata->nvars);
17487 oldbound = SCIPeventGetOldbound(event);
17488 newbound = SCIPeventGetNewbound(event);
17489 assert(var != NULL);
17490 assert(consdata->vars[varpos] == var);
17491 val = consdata->vals[varpos];
17492
17493 consdata->rangedrowpropagated = 0;
17494
17495 /* update the activity values */
17496 if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17497 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17498 else
17499 {
17500 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17501 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17502 }
17503
17504 /* if the variable is binary but not fixed it had to become binary due to this global change */
17506 {
17508 consdata->indexsorted = FALSE;
17509 else
17510 consdata->coefsorted = FALSE;
17511 }
17512 }
17513 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17514 {
17516
17517 /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17518 consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17519
17520 /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17521 consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17522 }
17523 else
17524 {
17525 assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17526 consdata->varsdeleted = TRUE;
17527 }
17528
17529 return SCIP_OKAY;
17530}
17531
17532
17533/*
17534 * Callback methods of conflict handler
17535 */
17536
17537/** conflict processing method of conflict handler (called when conflict was found) */
17538static
17539SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17540{ /*lint --e{715}*/
17541 SCIP_VAR** vars;
17542 SCIP_Real* vals;
17543 SCIP_Real lhs;
17544 int i;
17545
17546 assert(scip != NULL);
17547 assert(conflicthdlr != NULL);
17548 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17549 assert(bdchginfos != NULL || nbdchginfos == 0);
17550 assert(result != NULL);
17551
17552 /* don't process already resolved conflicts */
17553 if( resolved )
17554 {
17556 return SCIP_OKAY;
17557 }
17558
17560
17561 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17562 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17563 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17564 lhs = 1.0;
17565 for( i = 0; i < nbdchginfos; ++i )
17566 {
17567 assert(bdchginfos != NULL);
17568
17569 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17570
17571 /* we can only treat binary variables */
17572 /**@todo extend linear conflict constraints to some non-binary cases */
17573 if( !SCIPvarIsBinary(vars[i]) )
17574 break;
17575
17576 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17577 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17578 vals[i] = 1.0;
17579 else
17580 {
17581 vals[i] = -1.0;
17582 lhs -= 1.0;
17583 }
17584 }
17585
17586 if( i == nbdchginfos )
17587 {
17588 SCIP_CONS* cons;
17589 SCIP_CONS* upgdcons;
17590 char consname[SCIP_MAXSTRLEN];
17591
17592 /* create a constraint out of the conflict set */
17594 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17595 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17596
17597 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17598 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17599 if( upgdcons != NULL )
17600 {
17601 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17602 cons = upgdcons;
17603 }
17604
17605 /* add conflict to SCIP */
17606 SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17607
17609 }
17610
17611 /* free temporary memory */
17612 SCIPfreeBufferArray(scip, &vals);
17614
17615 return SCIP_OKAY;
17616}
17617
17618
17619/*
17620 * Nonlinear constraint upgrading
17621 */
17622
17623/** tries to upgrade a nonlinear constraint into a linear constraint */
17624static
17625SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17626{
17627 SCIP_CONSDATA* consdata;
17628 SCIP_EXPR* expr;
17629 SCIP_Real lhs;
17630 SCIP_Real rhs;
17631 int i;
17632
17633 assert(nupgdconss != NULL);
17634 assert(upgdconss != NULL);
17635 assert(upgdconsssize > 0);
17636
17637 expr = SCIPgetExprNonlinear(cons);
17638 assert(expr != NULL);
17639
17640 /* not a linear constraint if the expression is not a sum
17641 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17642 */
17643 if( !SCIPisExprSum(scip, expr) )
17644 return SCIP_OKAY;
17645
17646 /* if at least one child is not a variable, then not a linear constraint */
17647 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17648 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17649 return SCIP_OKAY;
17650
17651 /* consider constant part of the sum expression */
17654
17655 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17656 0, NULL, NULL, lhs, rhs,
17660 SCIPconsIsStickingAtNode(cons)) );
17661 assert(upgdconss[0] != NULL);
17662
17663 consdata = SCIPconsGetData(upgdconss[0]);
17664
17665 /* add linear terms */
17667 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17668 {
17670 }
17671
17672 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17673 consdata->checkabsolute = TRUE;
17674
17675 *nupgdconss = 1;
17676
17677 SCIPdebugMsg(scip, "created linear constraint:\n");
17678 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17679
17680 return SCIP_OKAY;
17681} /*lint !e715*/
17682
17683/*
17684 * constraint specific interface methods
17685 */
17686
17687/** creates the handler for linear constraints and includes it in SCIP */
17689 SCIP* scip /**< SCIP data structure */
17690 )
17691{
17692 SCIP_CONSHDLRDATA* conshdlrdata;
17693 SCIP_CONSHDLR* conshdlr;
17694 SCIP_EVENTHDLR* eventhdlr;
17695 SCIP_CONFLICTHDLR* conflicthdlr;
17696
17697 assert(scip != NULL);
17698
17699 /* create event handler for bound change events */
17701 eventExecLinear, NULL) );
17702
17703 /* create conflict handler for linear constraints */
17705 conflictExecLinear, NULL) );
17706
17707 /* create constraint handler data */
17708 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17709
17710 /* include constraint handler */
17713 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17714 conshdlrdata) );
17715
17716 assert(conshdlr != NULL);
17717
17718 /* set non-fundamental callbacks via specific setter functions */
17719 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17720 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17721 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17722 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17723 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17724 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17725 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17726 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17727 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17728 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17729 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17730 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17731 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17732 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17733 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17735 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17738 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17739 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17741 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17742 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17743 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17744 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17745
17746 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17747 {
17748 /* include the linear constraint upgrade in the nonlinear constraint handler */
17750 }
17751
17752 /* add linear constraint handler parameters */
17754 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17755 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17756 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17758 "constraints/" CONSHDLR_NAME "/maxrounds",
17759 "maximal number of separation rounds per node (-1: unlimited)",
17760 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17762 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17763 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17764 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17766 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17767 "maximal number of cuts separated per separation round",
17768 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17770 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17771 "maximal number of cuts separated per separation round in the root node",
17772 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17774 "constraints/" CONSHDLR_NAME "/presolpairwise",
17775 "should pairwise constraint comparison be performed in presolving?",
17776 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17778 "constraints/" CONSHDLR_NAME "/presolusehashing",
17779 "should hash table be used for detecting redundant constraints in advance",
17780 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17782 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17783 "number for minimal pairwise presolve comparisons",
17784 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17786 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17787 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17788 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17790 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17791 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17792 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17794 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17795 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17796 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17798 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17799 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17800 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17802 "constraints/" CONSHDLR_NAME "/separateall",
17803 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17804 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17806 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17807 "should presolving search for aggregations in equations",
17808 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17810 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17811 "should presolving try to simplify inequalities",
17812 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17814 "constraints/" CONSHDLR_NAME "/dualpresolving",
17815 "should dual presolving steps be performed?",
17816 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17818 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17819 "should stuffing of singleton continuous variables be performed?",
17820 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17822 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17823 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17824 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17826 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17827 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17829 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17830 "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)?",
17831 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17833 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17834 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17835 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17837 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17838 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17839 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17841 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17842 "should presolving try to detect subsets of constraints parallel to the objective function?",
17843 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17845 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17846 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17847 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17849 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17850 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17851 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17853 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17854 "maximum depth to apply ranged row propagation",
17855 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17857 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17858 "frequency for applying ranged row propagation",
17859 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17861 "constraints/" CONSHDLR_NAME "/multaggrremove",
17862 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17863 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17865 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17866 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17867 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17869 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17870 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17871 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17873 "constraints/" CONSHDLR_NAME "/extractcliques",
17874 "should Cliques be extracted?",
17875 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17876
17877 return SCIP_OKAY;
17878}
17879
17880/** includes a linear constraint update method into the linear constraint handler */
17882 SCIP* scip, /**< SCIP data structure */
17883 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17884 int priority, /**< priority of upgrading method */
17885 const char* conshdlrname /**< name of the constraint handler */
17886 )
17887{
17888 SCIP_CONSHDLR* conshdlr;
17889 SCIP_CONSHDLRDATA* conshdlrdata;
17890 SCIP_LINCONSUPGRADE* linconsupgrade;
17892 char paramdesc[SCIP_MAXSTRLEN];
17893
17894 assert(scip != NULL);
17895 assert(linconsupgd != NULL);
17896 assert(conshdlrname != NULL );
17897
17898 /* find the linear constraint handler */
17899 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17900 if( conshdlr == NULL )
17901 {
17902 SCIPerrorMessage("linear constraint handler not found\n");
17903 return SCIP_PLUGINNOTFOUND;
17904 }
17905
17906 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17907 assert(conshdlrdata != NULL);
17908
17909 /* check if linear constraint update method already exists in constraint handler data */
17910 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17911 {
17912 /* create a linear constraint upgrade data object */
17913 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17914
17915 /* insert linear constraint update method into constraint handler data */
17916 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17917
17918 /* adds parameter to turn on and off the upgrading step */
17919 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17920 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17922 paramname, paramdesc,
17923 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17924 }
17925
17926 return SCIP_OKAY;
17927}
17928
17929/** creates and captures a linear constraint
17930 *
17931 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17932 */
17934 SCIP* scip, /**< SCIP data structure */
17935 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17936 const char* name, /**< name of constraint */
17937 int nvars, /**< number of nonzeros in the constraint */
17938 SCIP_VAR** vars, /**< array with variables of constraint entries */
17939 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17940 SCIP_Real lhs, /**< left hand side of constraint */
17941 SCIP_Real rhs, /**< right hand side of constraint */
17942 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17943 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17944 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17945 * Usually set to TRUE. */
17946 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17947 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17948 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17949 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17950 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17951 * Usually set to TRUE. */
17952 SCIP_Bool local, /**< is constraint only valid locally?
17953 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17954 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17955 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17956 * adds coefficients to this constraint. */
17957 SCIP_Bool dynamic, /**< is constraint subject to aging?
17958 * Usually set to FALSE. Set to TRUE for own cuts which
17959 * are separated as constraints. */
17960 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17961 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17962 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17963 * if it may be moved to a more global node?
17964 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17965 )
17966{
17967 SCIP_CONSHDLR* conshdlr;
17968 SCIP_CONSDATA* consdata;
17969 int j;
17970
17971 assert(scip != NULL);
17972 assert(cons != NULL);
17973
17974 /* find the linear constraint handler */
17975 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17976 if( conshdlr == NULL )
17977 {
17978 SCIPerrorMessage("linear constraint handler not found\n");
17979 return SCIP_PLUGINNOTFOUND;
17980 }
17981
17982 for( j = 0; j < nvars; ++j )
17983 {
17984 if( SCIPisInfinity(scip, REALABS(vals[j])) )
17985 {
17986 SCIPerrorMessage("coefficient of variable <%s> is infinite.\n", SCIPvarGetName(vars[j]));
17987 SCIPABORT();
17988 return SCIP_INVALIDDATA;
17989 }
17990 }
17991
17992 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17993 * constraint after presolving we have to ensure that it holds active variables
17994 */
17996 {
17997 SCIP_VAR** consvars;
17998 SCIP_Real* consvals;
17999 SCIP_Real constant = 0.0;
18000 int nconsvars;
18001 int requiredsize;
18002
18003 nconsvars = nvars;
18004 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
18005 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
18006
18007 /* get active variables for new constraint */
18008 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18009
18010 /* if space was not enough we need to resize the buffers */
18011 if( requiredsize > nconsvars )
18012 {
18013 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18014 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18015
18016 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18017 assert(requiredsize <= nconsvars);
18018 }
18019
18020 /* adjust sides and check that we do not subtract infinity values */
18021 if( SCIPisInfinity(scip, REALABS(constant)) )
18022 {
18023 if( constant < 0.0 )
18024 {
18025 if( SCIPisInfinity(scip, lhs) )
18026 {
18027 SCIPfreeBufferArray(scip, &consvals);
18028 SCIPfreeBufferArray(scip, &consvars);
18029
18030 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);
18031
18032 SCIPABORT();
18033 return SCIP_INVALIDDATA; /*lint !e527*/
18034 }
18035 if( SCIPisInfinity(scip, rhs) )
18036 {
18037 SCIPfreeBufferArray(scip, &consvals);
18038 SCIPfreeBufferArray(scip, &consvars);
18039
18040 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);
18041
18042 SCIPABORT();
18043 return SCIP_INVALIDDATA; /*lint !e527*/
18044 }
18045
18046 lhs = -SCIPinfinity(scip);
18047 rhs = -SCIPinfinity(scip);
18048 }
18049 else
18050 {
18051 if( SCIPisInfinity(scip, -lhs) )
18052 {
18053 SCIPfreeBufferArray(scip, &consvals);
18054 SCIPfreeBufferArray(scip, &consvars);
18055
18056 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);
18057
18058 SCIPABORT();
18059 return SCIP_INVALIDDATA; /*lint !e527*/
18060 }
18061 if( SCIPisInfinity(scip, -rhs) )
18062 {
18063 SCIPfreeBufferArray(scip, &consvals);
18064 SCIPfreeBufferArray(scip, &consvars);
18065
18066 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);
18067
18068 SCIPABORT();
18069 return SCIP_INVALIDDATA; /*lint !e527*/
18070 }
18071
18072 lhs = SCIPinfinity(scip);
18073 rhs = SCIPinfinity(scip);
18074 }
18075 }
18076 else
18077 {
18078 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18079 lhs -= constant;
18080 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18081 rhs -= constant;
18082
18083 if( SCIPisInfinity(scip, -lhs) )
18084 lhs = -SCIPinfinity(scip);
18085 else if( SCIPisInfinity(scip, lhs) )
18086 lhs = SCIPinfinity(scip);
18087
18088 if( SCIPisInfinity(scip, rhs) )
18089 rhs = SCIPinfinity(scip);
18090 else if( SCIPisInfinity(scip, -rhs) )
18091 rhs = -SCIPinfinity(scip);
18092 }
18093
18094 /* create constraint data */
18095 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
18096 assert(consdata != NULL);
18097
18098 SCIPfreeBufferArray(scip, &consvals);
18099 SCIPfreeBufferArray(scip, &consvars);
18100 }
18101 else
18102 {
18103 /* create constraint data */
18104 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18105 assert(consdata != NULL);
18106 }
18107
18108#ifndef NDEBUG
18109 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18110 if( check || enforce )
18111 {
18112 int n;
18113 for(n = consdata->nvars - 1; n >= 0; --n )
18114 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18115 }
18116#endif
18117
18118 /* create constraint */
18119 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18120 local, modifiable, dynamic, removable, stickingatnode) );
18121
18122 return SCIP_OKAY;
18123}
18124
18125/** creates and captures a linear constraint
18126 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18127 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18128 *
18129 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18130 *
18131 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18132 */
18134 SCIP* scip, /**< SCIP data structure */
18135 SCIP_CONS** cons, /**< pointer to hold the created constraint */
18136 const char* name, /**< name of constraint */
18137 int nvars, /**< number of nonzeros in the constraint */
18138 SCIP_VAR** vars, /**< array with variables of constraint entries */
18139 SCIP_Real* vals, /**< array with coefficients of constraint entries */
18140 SCIP_Real lhs, /**< left hand side of constraint */
18141 SCIP_Real rhs /**< right hand side of constraint */
18142 )
18143{
18144 assert(scip != NULL);
18145
18146 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18148
18149 return SCIP_OKAY;
18150}
18151
18152/** creates by copying and captures a linear constraint */
18154 SCIP* scip, /**< target SCIP data structure */
18155 SCIP_CONS** cons, /**< pointer to store the created target constraint */
18156 SCIP* sourcescip, /**< source SCIP data structure */
18157 const char* name, /**< name of constraint */
18158 int nvars, /**< number of variables in source variable array */
18159 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18160 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18161 SCIP_Real lhs, /**< left hand side of the linear constraint */
18162 SCIP_Real rhs, /**< right hand side of the linear constraint */
18163 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18164 * variables of the target SCIP */
18165 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18166 * target constraints */
18167 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18168 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18169 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18170 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18171 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18172 SCIP_Bool local, /**< is constraint only valid locally? */
18173 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18174 SCIP_Bool dynamic, /**< is constraint subject to aging? */
18175 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18176 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18177 * if it may be moved to a more global node? */
18178 SCIP_Bool global, /**< create a global or a local copy? */
18179 SCIP_Bool* valid /**< pointer to store if the copying was valid */
18180 )
18181{
18182 SCIP_VAR** vars;
18183 SCIP_Real* coefs;
18184
18185 SCIP_Real constant;
18186 int requiredsize;
18187 int v;
18188 SCIP_Bool success;
18189
18190 if( SCIPisGT(scip, lhs, rhs) )
18191 {
18192 *valid = FALSE;
18193 return SCIP_OKAY;
18194 }
18195
18196 (*valid) = TRUE;
18197
18198 if( nvars == 0 )
18199 {
18200 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18201 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18202 return SCIP_OKAY;
18203 }
18204
18205 /* duplicate variable array */
18207
18208 /* duplicate coefficient array */
18209 if( sourcecoefs != NULL )
18210 {
18211 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18212 }
18213 else
18214 {
18216 for( v = 0; v < nvars; ++v )
18217 coefs[v] = 1.0;
18218 }
18219
18220 constant = 0.0;
18221
18222 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18223 * the target SCIP
18224 */
18225 if( !SCIPvarIsOriginal(vars[0]) )
18226 {
18227 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18228
18229 if( requiredsize > nvars )
18230 {
18231 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18232 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18233
18234 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18235 assert(requiredsize <= nvars);
18236 }
18237 }
18238 else
18239 {
18240 for( v = 0; v < nvars; ++v )
18241 {
18243 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18244 assert(vars[v] != NULL);
18245 }
18246 }
18247
18248 success = TRUE;
18249 /* map variables of the source constraint to variables of the target SCIP */
18250 for( v = 0; v < nvars && success; ++v )
18251 {
18252 SCIP_VAR* var;
18253 var = vars[v];
18254
18255 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18256 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18257
18258 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18259 assert(!(success) || vars[v] != NULL);
18260 }
18261
18262 /* only create the target constraint, if all variables could be copied */
18263 if( success )
18264 {
18265 if( !SCIPisInfinity(scip, -lhs) )
18266 lhs -= constant;
18267
18268 if( !SCIPisInfinity(scip, rhs) )
18269 rhs -= constant;
18270
18271 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18272 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18273 }
18274 else
18275 *valid = FALSE;
18276
18277 /* free buffer array */
18278 SCIPfreeBufferArray(scip, &coefs);
18280
18281 return SCIP_OKAY;
18282}
18283
18284/** adds coefficient to linear constraint (if it is not zero) */
18286 SCIP* scip, /**< SCIP data structure */
18287 SCIP_CONS* cons, /**< constraint data */
18288 SCIP_VAR* var, /**< variable of constraint entry */
18289 SCIP_Real val /**< coefficient of constraint entry */
18290 )
18291{
18292 assert(scip != NULL);
18293 assert(cons != NULL);
18294 assert(var != NULL);
18295
18296 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18297 {
18298 SCIPerrorMessage("constraint is not linear\n");
18299 return SCIP_INVALIDDATA;
18300 }
18301
18302 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18303 * constraint after presolving we have to ensure that it holds active variables
18304 */
18306 {
18307 SCIP_CONSDATA* consdata;
18308 SCIP_VAR** consvars;
18309 SCIP_Real* consvals;
18310 SCIP_Real constant = 0.0;
18311 SCIP_Real rhs;
18312 SCIP_Real lhs;
18313 int nconsvars;
18314 int requiredsize;
18315 int v;
18316
18317 nconsvars = 1;
18318 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18319 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18320 consvars[0] = var;
18321 consvals[0] = val;
18322
18323 /* get active variables for new constraint */
18324 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18325
18326 /* if space was not enough we need to resize the buffers */
18327 if( requiredsize > nconsvars )
18328 {
18329 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18330 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18331
18332 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18333 assert(requiredsize <= nconsvars);
18334 }
18335
18336 consdata = SCIPconsGetData(cons);
18337 assert(consdata != NULL);
18338
18339 lhs = consdata->lhs;
18340 rhs = consdata->rhs;
18341
18342 /* adjust sides and check that we do not subtract infinity values */
18343 /* constant is infinite */
18344 if( SCIPisInfinity(scip, REALABS(constant)) )
18345 {
18346 if( constant < 0.0 )
18347 {
18348 if( SCIPisInfinity(scip, lhs) )
18349 {
18350 SCIPfreeBufferArray(scip, &consvals);
18351 SCIPfreeBufferArray(scip, &consvars);
18352
18353 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));
18354
18355 SCIPABORT();
18356 return SCIP_INVALIDDATA; /*lint !e527*/
18357 }
18358 if( SCIPisInfinity(scip, rhs) )
18359 {
18360 SCIPfreeBufferArray(scip, &consvals);
18361 SCIPfreeBufferArray(scip, &consvars);
18362
18363 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));
18364
18365 SCIPABORT();
18366 return SCIP_INVALIDDATA; /*lint !e527*/
18367 }
18368
18369 lhs = -SCIPinfinity(scip);
18370 rhs = -SCIPinfinity(scip);
18371 }
18372 else
18373 {
18374 if( SCIPisInfinity(scip, -lhs) )
18375 {
18376 SCIPfreeBufferArray(scip, &consvals);
18377 SCIPfreeBufferArray(scip, &consvars);
18378
18379 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));
18380
18381 SCIPABORT();
18382 return SCIP_INVALIDDATA; /*lint !e527*/
18383 }
18384 if( SCIPisInfinity(scip, -rhs) )
18385 {
18386 SCIPfreeBufferArray(scip, &consvals);
18387 SCIPfreeBufferArray(scip, &consvars);
18388
18389 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));
18390
18391 SCIPABORT();
18392 return SCIP_INVALIDDATA; /*lint !e527*/
18393 }
18394
18395 lhs = SCIPinfinity(scip);
18396 rhs = SCIPinfinity(scip);
18397 }
18398 }
18399 /* constant is not infinite */
18400 else
18401 {
18402 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18403 lhs -= constant;
18404 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18405 rhs -= constant;
18406
18407 if( SCIPisInfinity(scip, -lhs) )
18408 lhs = -SCIPinfinity(scip);
18409 else if( SCIPisInfinity(scip, lhs) )
18410 lhs = SCIPinfinity(scip);
18411
18412 if( SCIPisInfinity(scip, rhs) )
18413 rhs = SCIPinfinity(scip);
18414 else if( SCIPisInfinity(scip, -rhs) )
18415 rhs = -SCIPinfinity(scip);
18416 }
18417
18418 /* add all active variables to constraint */
18419 for( v = nconsvars - 1; v >= 0; --v )
18420 {
18421 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18422 }
18423
18424 /* update left and right hand sides */
18425 SCIP_CALL( chgLhs(scip, cons, lhs));
18426 SCIP_CALL( chgRhs(scip, cons, rhs));
18427
18428 SCIPfreeBufferArray(scip, &consvals);
18429 SCIPfreeBufferArray(scip, &consvars);
18430 }
18431 else
18432 {
18433 SCIP_CALL( addCoef(scip, cons, var, val) );
18434 }
18435
18436 return SCIP_OKAY;
18437}
18438
18439/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18440 * not yet contained in the constraint
18441 *
18442 * @note This method may only be called during problem creation stage for an original constraint and variable.
18443 *
18444 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18445 */
18447 SCIP* scip, /**< SCIP data structure */
18448 SCIP_CONS* cons, /**< constraint data */
18449 SCIP_VAR* var, /**< variable of constraint entry */
18450 SCIP_Real val /**< new coefficient of constraint entry */
18451 )
18452{
18453 SCIP_CONSDATA* consdata;
18454 SCIP_VAR** vars;
18455 SCIP_Bool found;
18456 int i;
18457
18458 assert(scip != NULL);
18459 assert(cons != NULL);
18460 assert(var != NULL);
18461
18462 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18463 {
18464 SCIPerrorMessage("constraint is not linear\n");
18465 return SCIP_INVALIDDATA;
18466 }
18467
18469 {
18470 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18471 return SCIP_INVALIDDATA;
18472 }
18473
18474 consdata = SCIPconsGetData(cons);
18475 assert(consdata != NULL);
18476
18477 vars = consdata->vars;
18478 found = FALSE;
18479 i = 0;
18480 while( i < consdata->nvars )
18481 {
18482 if( vars[i] == var )
18483 {
18484 if( found || SCIPisZero(scip, val) )
18485 {
18486 SCIP_CALL( delCoefPos(scip, cons, i) );
18487
18488 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18489 i--;
18490 }
18491 else
18492 {
18493 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18494 }
18495 found = TRUE;
18496 }
18497 i++;
18498 }
18499
18500 if( !found && !SCIPisZero(scip, val) )
18501 {
18502 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18503 }
18504
18505 return SCIP_OKAY;
18506}
18507
18508/** deletes variable from linear constraint
18509 *
18510 * @note This method may only be called during problem creation stage for an original constraint and variable.
18511 *
18512 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18513 */
18515 SCIP* scip, /**< SCIP data structure */
18516 SCIP_CONS* cons, /**< constraint data */
18517 SCIP_VAR* var /**< variable of constraint entry */
18518 )
18519{
18520 assert(scip != NULL);
18521 assert(cons != NULL);
18522 assert(var != NULL);
18523
18524 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18525
18526 return SCIP_OKAY;
18527}
18528
18529/** gets left hand side of linear constraint */
18531 SCIP* scip, /**< SCIP data structure */
18532 SCIP_CONS* cons /**< constraint data */
18533 )
18534{
18535 SCIP_CONSDATA* consdata;
18536
18537 assert(scip != NULL);
18538 assert(cons != NULL);
18539
18540 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18541 {
18542 SCIPerrorMessage("constraint is not linear\n");
18543 SCIPABORT();
18544 return SCIP_INVALID; /*lint !e527*/
18545 }
18546
18547 consdata = SCIPconsGetData(cons);
18548 assert(consdata != NULL);
18549
18550 return consdata->lhs;
18551}
18552
18553/** gets right hand side of linear constraint */
18555 SCIP* scip, /**< SCIP data structure */
18556 SCIP_CONS* cons /**< constraint data */
18557 )
18558{
18559 SCIP_CONSDATA* consdata;
18560
18561 assert(scip != NULL);
18562 assert(cons != NULL);
18563
18564 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18565 {
18566 SCIPerrorMessage("constraint is not linear\n");
18567 SCIPABORT();
18568 return SCIP_INVALID; /*lint !e527*/
18569 }
18570
18571 consdata = SCIPconsGetData(cons);
18572 assert(consdata != NULL);
18573
18574 return consdata->rhs;
18575}
18576
18577/** changes left hand side of linear constraint */
18579 SCIP* scip, /**< SCIP data structure */
18580 SCIP_CONS* cons, /**< constraint data */
18581 SCIP_Real lhs /**< new left hand side */
18582 )
18583{
18584 assert(scip != NULL);
18585 assert(cons != NULL);
18586
18587 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18588 {
18589 SCIPerrorMessage("constraint is not linear\n");
18590 return SCIP_INVALIDDATA;
18591 }
18592
18593 SCIP_CALL( chgLhs(scip, cons, lhs) );
18594
18595 return SCIP_OKAY;
18596}
18597
18598/** changes right hand side of linear constraint */
18600 SCIP* scip, /**< SCIP data structure */
18601 SCIP_CONS* cons, /**< constraint data */
18602 SCIP_Real rhs /**< new right hand side */
18603 )
18604{
18605 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18606 {
18607 SCIPerrorMessage("constraint is not linear\n");
18608 return SCIP_INVALIDDATA;
18609 }
18610
18611 SCIP_CALL( chgRhs(scip, cons, rhs) );
18612
18613 return SCIP_OKAY;
18614}
18615
18616/** gets the number of variables in the linear constraint */
18618 SCIP* scip, /**< SCIP data structure */
18619 SCIP_CONS* cons /**< constraint data */
18620 )
18621{
18622 SCIP_CONSDATA* consdata;
18623
18624 assert(scip != NULL);
18625 assert(cons != NULL);
18626
18627 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18628 {
18629 SCIPerrorMessage("constraint is not linear\n");
18630 SCIPABORT();
18631 return -1; /*lint !e527*/
18632 }
18633
18634 consdata = SCIPconsGetData(cons);
18635 assert(consdata != NULL);
18636
18637 return consdata->nvars;
18638}
18639
18640/** gets the array of variables in the linear constraint; the user must not modify this array! */
18642 SCIP* scip, /**< SCIP data structure */
18643 SCIP_CONS* cons /**< constraint data */
18644 )
18645{
18646 SCIP_CONSDATA* consdata;
18647
18648 assert(scip != NULL);
18649 assert(cons != NULL);
18650
18651 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18652 {
18653 SCIPerrorMessage("constraint is not linear\n");
18654 SCIPABORT();
18655 return NULL; /*lint !e527*/
18656 }
18657
18658 consdata = SCIPconsGetData(cons);
18659 assert(consdata != NULL);
18660
18661 return consdata->vars;
18662}
18663
18664/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18666 SCIP* scip, /**< SCIP data structure */
18667 SCIP_CONS* cons /**< constraint data */
18668 )
18669{
18670 SCIP_CONSDATA* consdata;
18671
18672 assert(scip != NULL);
18673 assert(cons != NULL);
18674
18675 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18676 {
18677 SCIPerrorMessage("constraint is not linear\n");
18678 SCIPABORT();
18679 return NULL; /*lint !e527*/
18680 }
18681
18682 consdata = SCIPconsGetData(cons);
18683 assert(consdata != NULL);
18684
18685 return consdata->vals;
18686}
18687
18688/** gets the activity of the linear constraint in the given solution
18689 *
18690 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18691 * comprises positive and negative infinity contributions
18692 */
18694 SCIP* scip, /**< SCIP data structure */
18695 SCIP_CONS* cons, /**< constraint data */
18696 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18697 )
18698{
18699 SCIP_CONSDATA* consdata;
18700
18701 assert(scip != NULL);
18702 assert(cons != NULL);
18703
18704 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18705 {
18706 SCIPerrorMessage("constraint is not linear\n");
18707 SCIPABORT();
18708 return SCIP_INVALID; /*lint !e527*/
18709 }
18710
18711 consdata = SCIPconsGetData(cons);
18712 assert(consdata != NULL);
18713
18714 if( consdata->row != NULL )
18715 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18716 else
18717 return consdataGetActivity(scip, consdata, sol);
18718}
18719
18720/** gets the feasibility of the linear constraint in the given solution */
18722 SCIP* scip, /**< SCIP data structure */
18723 SCIP_CONS* cons, /**< constraint data */
18724 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18725 )
18726{
18727 SCIP_CONSDATA* consdata;
18728
18729 assert(scip != NULL);
18730 assert(cons != NULL);
18731
18732 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18733 {
18734 SCIPerrorMessage("constraint is not linear\n");
18735 SCIPABORT();
18736 return SCIP_INVALID; /*lint !e527*/
18737 }
18738
18739 consdata = SCIPconsGetData(cons);
18740 assert(consdata != NULL);
18741
18742 if( consdata->row != NULL )
18743 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18744 else
18745 return consdataGetFeasibility(scip, consdata, sol);
18746}
18747
18748/** gets the dual solution of the linear constraint in the current LP */
18750 SCIP* scip, /**< SCIP data structure */
18751 SCIP_CONS* cons /**< constraint data */
18752 )
18753{
18754 SCIP_CONSDATA* consdata;
18755
18756 assert(scip != NULL);
18757 assert(cons != NULL);
18758 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18759
18760 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18761 {
18762 SCIPerrorMessage("constraint is not linear\n");
18763 SCIPABORT();
18764 return SCIP_INVALID; /*lint !e527*/
18765 }
18766
18767 consdata = SCIPconsGetData(cons);
18768 assert(consdata != NULL);
18769
18770 if( consdata->row != NULL )
18771 return SCIProwGetDualsol(consdata->row);
18772 else
18773 return 0.0;
18774}
18775
18776/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18778 SCIP* scip, /**< SCIP data structure */
18779 SCIP_CONS* cons /**< constraint data */
18780 )
18781{
18782 SCIP_CONSDATA* consdata;
18783
18784 assert(scip != NULL);
18785 assert(cons != NULL);
18786 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18787
18788 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18789 {
18790 SCIPerrorMessage("constraint is not linear\n");
18791 SCIPABORT();
18792 return SCIP_INVALID; /*lint !e527*/
18793 }
18794
18795 consdata = SCIPconsGetData(cons);
18796 assert(consdata != NULL);
18797
18798 if( consdata->row != NULL )
18799 return SCIProwGetDualfarkas(consdata->row);
18800 else
18801 return 0.0;
18802}
18803
18804/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18805 * the user must not modify the row!
18806 */
18808 SCIP* scip, /**< SCIP data structure */
18809 SCIP_CONS* cons /**< constraint data */
18810 )
18811{
18812 SCIP_CONSDATA* consdata;
18813
18814 assert(scip != NULL);
18815 assert(cons != NULL);
18816
18817 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18818 {
18819 SCIPerrorMessage("constraint is not linear\n");
18820 SCIPABORT();
18821 return NULL; /*lint !e527*/
18822 }
18823
18824 consdata = SCIPconsGetData(cons);
18825 assert(consdata != NULL);
18826
18827 return consdata->row;
18828}
18829
18830/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18832 SCIP* scip, /**< SCIP data structure */
18833 SCIP_CONS* cons, /**< source constraint to try to convert */
18834 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18835 )
18836{
18837 SCIP_CONSHDLR* conshdlr;
18838 SCIP_CONSHDLRDATA* conshdlrdata;
18839 SCIP_CONSDATA* consdata;
18840 SCIP_VAR* var;
18841 SCIP_Real val;
18842 SCIP_Real lb;
18843 SCIP_Real ub;
18844 SCIP_Real poscoeffsum;
18845 SCIP_Real negcoeffsum;
18846 SCIP_Bool infeasible;
18847 SCIP_Bool integral;
18848 int nchgsides = 0;
18849 int nposbin;
18850 int nnegbin;
18851 int nposint;
18852 int nnegint;
18853 int nposimpl;
18854 int nnegimpl;
18855 int nposimplbin;
18856 int nnegimplbin;
18857 int nposcont;
18858 int nnegcont;
18859 int ncoeffspone;
18860 int ncoeffsnone;
18861 int ncoeffspint;
18862 int ncoeffsnint;
18863 int ncoeffspfrac;
18864 int ncoeffsnfrac;
18865 int i;
18866
18867 assert(scip != NULL);
18868 assert(cons != NULL);
18869 assert(upgdcons != NULL);
18870
18871 *upgdcons = NULL;
18872
18873 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18874 if( SCIPconsIsModifiable(cons) )
18875 return SCIP_OKAY;
18876
18877 /* check for upgradability */
18878 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18879 return SCIP_OKAY;
18880
18881 /* get the constraint handler and check, if it's really a linear constraint */
18882 conshdlr = SCIPconsGetHdlr(cons);
18883 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18884 {
18885 SCIPerrorMessage("constraint is not linear\n");
18886 return SCIP_INVALIDDATA;
18887 }
18888
18889 /* get constraint handler data and constraint data */
18890 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18891 assert(conshdlrdata != NULL);
18892 consdata = SCIPconsGetData(cons);
18893 assert(consdata != NULL);
18894
18895 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18896 if( consdata->upgraded )
18897 return SCIP_OKAY;
18898
18899 /* check, if the constraint is already stored as LP row */
18900 if( consdata->row != NULL )
18901 {
18902 if( SCIProwIsInLP(consdata->row) )
18903 {
18904 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18905 return SCIP_INVALIDDATA;
18906 }
18907 else
18908 {
18909 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18910 }
18911 }
18912
18913 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18914
18915 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18916 * skipped and we hope that the infeasibility gets detected later again.
18917 *
18918 * TODO: do we want to try to upgrade the constraint anyway?
18919 *
18920 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18921 * proven to be infeasible.
18922 */
18923 if( infeasible ) /*lint !e774*/
18924 return SCIP_OKAY;
18925
18926 /* tighten sides */
18927 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18928
18929 if( infeasible ) /*lint !e774*/
18930 return SCIP_OKAY;
18931
18932 /*
18933 * calculate some statistics on linear constraint
18934 */
18935
18936 nposbin = 0;
18937 nnegbin = 0;
18938 nposint = 0;
18939 nnegint = 0;
18940 nposimpl = 0;
18941 nnegimpl = 0;
18942 nposimplbin = 0;
18943 nnegimplbin = 0;
18944 nposcont = 0;
18945 nnegcont = 0;
18946 ncoeffspone = 0;
18947 ncoeffsnone = 0;
18948 ncoeffspint = 0;
18949 ncoeffsnint = 0;
18950 ncoeffspfrac = 0;
18951 ncoeffsnfrac = 0;
18952 integral = TRUE;
18953 poscoeffsum = 0.0;
18954 negcoeffsum = 0.0;
18955
18956 for( i = 0; i < consdata->nvars; ++i )
18957 {
18958 var = consdata->vars[i];
18959 val = consdata->vals[i];
18960 lb = SCIPvarGetLbLocal(var);
18961 ub = SCIPvarGetUbLocal(var);
18962 assert(!SCIPisZero(scip, val));
18963
18964 switch( SCIPvarGetType(var) )
18965 {
18967 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18968 integral = integral && SCIPisIntegral(scip, val);
18969 if( val >= 0.0 )
18970 nposbin++;
18971 else
18972 nnegbin++;
18973 break;
18975 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18976 integral = integral && SCIPisIntegral(scip, val);
18977 if( val >= 0.0 )
18978 nposint++;
18979 else
18980 nnegint++;
18981 break;
18983 if( SCIPvarIsBinary(var) )
18984 {
18985 if( val >= 0.0 )
18986 nposimplbin++;
18987 else
18988 nnegimplbin++;
18989 }
18990 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18991 integral = integral && SCIPisIntegral(scip, val);
18992 if( val >= 0.0 )
18993 nposimpl++;
18994 else
18995 nnegimpl++;
18996 break;
18998 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18999 if( val >= 0.0 )
19000 nposcont++;
19001 else
19002 nnegcont++;
19003 break;
19004 default:
19005 SCIPerrorMessage("unknown variable type\n");
19006 return SCIP_INVALIDDATA;
19007 }
19008 if( SCIPisEQ(scip, val, 1.0) )
19009 ncoeffspone++;
19010 else if( SCIPisEQ(scip, val, -1.0) )
19011 ncoeffsnone++;
19012 else if( SCIPisIntegral(scip, val) )
19013 {
19014 if( SCIPisPositive(scip, val) )
19015 ncoeffspint++;
19016 else
19017 ncoeffsnint++;
19018 }
19019 else
19020 {
19021 if( SCIPisPositive(scip, val) )
19022 ncoeffspfrac++;
19023 else
19024 ncoeffsnfrac++;
19025 }
19026 if( SCIPisPositive(scip, val) )
19027 poscoeffsum += val;
19028 else
19029 negcoeffsum += val;
19030 }
19031
19032 /*
19033 * call the upgrading methods
19034 */
19035
19036 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
19037 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
19038 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",
19039 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
19040 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
19041 poscoeffsum, negcoeffsum, integral);
19042
19043 /* try all upgrading methods in priority order in case the upgrading step is enable */
19044 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
19045 {
19046 if( conshdlrdata->linconsupgrades[i]->active )
19047 {
19048 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
19049 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
19050 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
19051 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
19052 poscoeffsum, negcoeffsum, integral,
19053 upgdcons) );
19054 }
19055 }
19056
19057#ifdef SCIP_DEBUG
19058 if( *upgdcons != NULL )
19059 {
19061 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
19062 SCIPdebugPrintCons(scip, *upgdcons, NULL);
19063 }
19064#endif
19065
19066 return SCIP_OKAY; /*lint !e438*/
19067}
19068
19069/** cleans up (multi-)aggregations and fixings from linear constraints */
19071 SCIP* scip, /**< SCIP data structure */
19072 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
19073 SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
19074 )
19075{
19076 SCIP_CONSHDLR* conshdlr;
19077 SCIP_CONS** conss;
19078 int nconss;
19079 int i;
19080
19081 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
19082 if( conshdlr == NULL )
19083 return SCIP_OKAY;
19084
19085 assert(infeasible != NULL);
19086 *infeasible = FALSE;
19087
19088 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
19089 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
19090
19091 for( i = 0; i < nconss; ++i )
19092 {
19093 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
19094
19095 if( *infeasible )
19096 break;
19097 }
19098
19099 return SCIP_OKAY;
19100}
static long bound
SCIP_VAR * w
SCIP_VAR * a
SCIP_VAR ** b
SCIP_VAR ** x
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
enum Proprule PROPRULE
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
#define DEFAULT_AGGREGATEVARIABLES
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
#define DEFAULT_NMINCOMPARISONS
#define DEFAULT_MULTAGGRREMOVE
#define DEFAULT_DUALPRESOLVING
#define DEFAULT_EXTRACTCLIQUES
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
#define CONSHDLR_NEEDSCONS
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
#define CONSHDLR_SEPAFREQ
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool checkrelmaxabs, SCIP_Bool *violated)
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
#define CONFLICTHDLR_PRIORITY
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define CONFLICTHDLR_NAME
#define MAXDNOM
static SCIP_RETCODE conshdlrdataIncludeUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_LINCONSUPGRADE *linconsupgrade)
static SCIP_RETCODE extractCliques(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, int *nfixedvars, int *nchgbds, SCIP_Bool *cutoff)
#define CONSHDLR_CHECKPRIORITY
#define CONSHDLR_DESC
Definition cons_linear.c:97
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
static int getVarWeight(SCIP_VAR *var)
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
#define DEFAULT_DETECTCUTOFFBOUND
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)
#define CONSHDLR_PROP_TIMING
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
static SCIP_RETCODE retrieveParallelConstraints(SCIP_HASHTABLE *hashtable, SCIP_CONS **querycons, SCIP_CONS **parallelconss, int *nparallelconss)
#define CONFLICTHDLR_DESC
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
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)
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static void consdataUpdateActivitiesUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
static void consdataUpdateActivitiesLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
#define CONSHDLR_MAXPREROUNDS
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
#define DEFAULT_PRESOLPAIRWISE
#define DEFAULT_MAXAGGRNORMSCALE
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
#define checkMaxActivityDelta(scip, consdata)
#define CONSHDLR_SEPAPRIORITY
Definition cons_linear.c:98
static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
#define DEFAULT_SINGLETONSTUFFING
#define DEFAULT_MAXROUNDSROOT
static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
#define MINVALRECOMP
#define DEFAULT_MAXCARDBOUNDDIST
#define DEFAULT_MAXEASYACTIVITYDELTA
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
static int inferInfoGetPos(INFERINFO inferinfo)
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
#define DEFAULT_MAXDUALMULTAGGRQUOT
static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
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_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
static INFERINFO intToInferInfo(int i)
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
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)
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)
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
#define DEFAULT_SORTVARS
#define DEFAULT_MAXMULTAGGRQUOT
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
#define MAXCONSPRESOLROUNDS
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
#define MAXACTVAL
#define NONLINCONSUPGD_PRIORITY
#define DEFAULT_MAXSEPACUTSROOT
@ PROPRULE_1_RANGEDROW
@ PROPRULE_1_LHS
@ PROPRULE_INVALID
@ PROPRULE_1_RHS
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
#define DEFAULT_RANGEDROWPROPAGATION
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
#define DEFAULT_PRESOLUSEHASHING
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
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)
static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
#define DEFAULT_RANGEDROWFREQ
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)
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)
#define DEFAULT_RANGEDROWARTCONS
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
#define MAXSCALEDCOEFINTEGER
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
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)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
#define BINWEIGHT
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
#define DEFAULT_SIMPLIFYINEQUALITIES
#define CONSHDLR_PROPFREQ
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
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)
static SCIP_RETCODE convertEquality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
static unsigned int getParallelConsKey(SCIP_CONS *cons)
#define CONTWEIGHT
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
#define CONSHDLR_PRESOLTIMING
#define DEFAULT_DETECTPARTIALOBJECTIVE
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)
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
#define DEFAULT_MAXSEPACUTS
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)
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
#define CONSHDLR_EAGERFREQ
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)
#define DEFAULT_TIGHTENBOUNDSFREQ
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
#define EVENTHDLR_DESC
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
#define DEFAULT_MAXROUNDS
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)
#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)
static int getInferInt(PROPRULE proprule, int pos)
static int inferInfoGetProprule(INFERINFO inferinfo)
#define DEFAULT_MINGAINPERNMINCOMP
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
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
#define MAXSCALEDCOEF
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
#define DEFAULT_RANGEDROWMAXDEPTH
static SCIP_RETCODE analyzeConflictRangedRow(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
#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)
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)
#define DEFAULT_SINGLEVARSTUFFING
#define EVENTHDLR_NAME
#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)
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, INFERINFO inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
#define DEFAULT_DETECTLOWERBOUND
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
#define MAXVALRECOMP
#define CONSHDLR_DELAYPROP
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)
static SCIP_Bool canTightenBounds(SCIP_CONS *cons)
#define DEFAULT_SEPARATEALL
static void findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
#define MAXTIGHTENROUNDS
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 MIN(x, y)
Definition def.h:243
#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 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)
#define SCIP_DECL_NONLINCONSUPGD(x)
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)
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)
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
SCIP_Bool SCIPisStopped(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
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
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
#define SCIPhashSeven(a, b, c, d, e, f, g)
Definition pub_misc.h:567
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition misc.c:2804
static INLINE uint32_t SCIPrealHashCode(double x)
Definition pub_misc.h:576
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,...)
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
#define SCIPdebugMsgPrint
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
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
int SCIPgetNLPBranchCands(SCIP *scip)
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
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition cons.c:4227
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:670
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 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 SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:323
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 SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:808
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:831
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:785
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition cons.c:5140
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:924
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4636
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4197
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)),)
Definition scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:941
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:396
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:900
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:444
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:693
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4217
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4670
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:647
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:516
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:468
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4593
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:762
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:420
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:624
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:854
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:3854
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:3864
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)
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:1737
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:5202
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:4350
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:6920
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition scip_var.c:1479
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:8564
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:18144
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:8597
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:8400
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:5614
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:5319
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:1793
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:4258
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:4436
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2127
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:8534
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18680
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1247
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition scip_var.c:4644
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:4612
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:8175
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1692
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:6779
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:8275
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:5500
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:1991
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:4512
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:1438
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1213
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition scip_var.c:8628
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:5431
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
return SCIP_OKAY
int c
int depth
SCIP_Bool cutoff
SCIP_Real objval
static SCIP_SOL * sol
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
SCIP_Real frac
static SCIP_Bool propagate
static SCIP_VAR ** vars
SCIP_Real alpha
int nbinvars
int nintvars
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
#define SCIPdebug(x)
Definition pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
#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
#define SCIP_DECL_CONFLICTEXEC(x)
@ SCIP_CONFTYPE_PROPAGATION
#define SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(x)
Definition type_cons.h:955
#define SCIP_DECL_CONSGETPERMSYMGRAPH(x)
Definition type_cons.h:937
#define SCIP_DECL_CONSENFOLP(x)
Definition type_cons.h:363
#define SCIP_DECL_CONSDELETE(x)
Definition type_cons.h:229
#define SCIP_DECL_CONSEXIT(x)
Definition type_cons.h:136
#define SCIP_DECL_CONSGETVARS(x)
Definition type_cons.h:866
#define SCIP_DECL_CONSINITSOL(x)
Definition type_cons.h:201
#define SCIP_DECL_CONSPRINT(x)
Definition type_cons.h:768
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition type_cons.h:64
#define SCIP_DECL_CONSSEPALP(x)
Definition type_cons.h:288
#define SCIP_DECL_CONSENFORELAX(x)
Definition type_cons.h:388
#define SCIP_DECL_CONSPROP(x)
Definition type_cons.h:505
#define SCIP_DECL_CONSGETNVARS(x)
Definition type_cons.h:884
#define SCIP_DECL_CONSRESPROP(x)
Definition type_cons.h:611
@ 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
#define SCIP_DECL_CONSACTIVE(x)
Definition type_cons.h:690
#define SCIP_DECL_CONSENFOPS(x)
Definition type_cons.h:431
#define SCIP_DECL_CONSPARSE(x)
Definition type_cons.h:844
#define SCIP_DECL_CONSTRANS(x)
Definition type_cons.h:239
#define SCIP_DECL_CONSDEACTIVE(x)
Definition type_cons.h:705
#define SCIP_DECL_CONSPRESOL(x)
Definition type_cons.h:560
#define SCIP_DECL_CONSINITLP(x)
Definition type_cons.h:259
#define SCIP_DECL_CONSEXITPRE(x)
Definition type_cons.h:180
#define SCIP_DECL_CONSLOCK(x)
Definition type_cons.h:675
#define SCIP_DECL_CONSCOPY(x)
Definition type_cons.h:809
#define SCIP_DECL_CONSINIT(x)
Definition type_cons.h:126
struct SCIP_ConsData SCIP_CONSDATA
Definition type_cons.h:65
#define SCIP_DECL_CONSCHECK(x)
Definition type_cons.h:474
#define SCIP_DECL_CONSHDLRCOPY(x)
Definition type_cons.h:108
#define SCIP_DECL_CONSEXITSOL(x)
Definition type_cons.h:216
#define SCIP_DECL_CONSFREE(x)
Definition type_cons.h:116
#define SCIP_DECL_CONSSEPASOL(x)
Definition type_cons.h:320
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition type_cons.h:91
#define SCIP_DECL_CONSDELVARS(x)
Definition type_cons.h:752
#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_DECL_EVENTEXEC(x)
Definition type_event.h:253
#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
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:194
#define SCIP_DECL_SORTINDCOMP(x)
Definition type_misc.h:180
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:191
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:197
@ 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
@ SCIP_INVALIDDATA
@ SCIP_PLUGINNOTFOUND
enum SCIP_Retcode SCIP_RETCODE
@ 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
@ SYM_SYMTYPE_SIGNPERM
@ SYM_SYMTYPE_PERM
#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