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
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
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);
518
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);
537
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);
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);
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
904 SCIP_Real* valsbuffer;
905
906 /* copy variables into temporary buffer */
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 */
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;
1268 SCIP_Real pseudoactivity;
1269 SCIP_Real bound;
1270 SCIP_Real val;
1271
1272 pseudoactivity = 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 )
1284 else
1286 }
1287 else
1288 {
1289 if( SCIPisInfinity(scip, -bound) )
1290 {
1291 if( val > 0.0 )
1293 else
1295 }
1296 else
1297 pseudoactivity += val * bound;
1298 }
1299 }
1300
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];
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];
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;
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
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
1841 }
1842 }
1843 }
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
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
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)++;
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)++;
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)++;
1943 }
1944 else
1945 {
1946 (*activityneghuge)++;
1948 }
1949 }
1950 /* "normal case": just update the activity */
1951 else
1952 {
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);
1970
1972 {
1973 (*lastactivity) = curractivity;
1974 }
1975 else
1976 {
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 {
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 {
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 {
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 {
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
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
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* isrelax, /**< pointer to store whether the activity is a relaxation,
2415 * i.e. is <= the exact minactivity (in case of huge contributing values) */
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(isrelax != NULL);
2428
2429 /* if we have pos. infinite contributions, the minactivity is +infty */
2430 if( posinf > 0 )
2431 {
2432 *minactivity = SCIPinfinity(scip);
2434 *isrelax = FALSE;
2435 }
2436 /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2437 else if( neginf > 0 )
2438 {
2439 *minactivity = -SCIPinfinity(scip);
2441 *isrelax = FALSE;
2442 }
2443 /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2444 else if( neghuge > 0 )
2445 {
2446 *minactivity = -SCIPinfinity(scip);
2448 *isrelax = TRUE;
2449 }
2450 /* we do not need a good relaxation and we have positive huge contributions, so we just return -infty as activity */
2451 else if( !goodrelax && poshuge > 0 )
2452 {
2453 *minactivity = -SCIPinfinity(scip);
2455 *isrelax = TRUE;
2456 }
2457 else
2458 {
2459 SCIP_Real tmpactivity;
2460
2461 /* recompute minactivity if it is not valid */
2462 if( global )
2463 {
2464 if( !consdata->validglbminact )
2466 assert(consdata->validglbminact);
2467
2468 tmpactivity = QUAD_TO_DBL(consdata->glbminactivity);
2469 }
2470 else
2471 {
2472 if( !consdata->validminact )
2474 assert(consdata->validminact);
2475
2476 tmpactivity = QUAD_TO_DBL(consdata->minactivity);
2477 }
2478
2479 /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2480 * a feasible relaxation of the minactivity is the number of positive huge contributions
2481 * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2482 */
2483 if( poshuge > 0 )
2484 {
2485 *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2487 *isrelax = TRUE;
2488 }
2489 /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2490 else
2491 {
2492 *minactivity = tmpactivity - delta;
2494 *isrelax = FALSE;
2495 }
2496 }
2497}
2498
2499/** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2500 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2501 */
2502static
2504 SCIP* scip, /**< SCIP data structure */
2505 SCIP_CONSDATA* consdata, /**< linear constraint */
2506 int posinf, /**< number of coefficients contributing pos. infinite value */
2507 int neginf, /**< number of coefficients contributing neg. infinite value */
2508 int poshuge, /**< number of coefficients contributing huge pos. value */
2509 int neghuge, /**< number of coefficients contributing huge neg. value */
2510 SCIP_Real delta, /**< value to subtract from stored maxactivity
2511 * (contribution of the variable set to zero when getting residual activity) */
2512 SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2513 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2514 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2515 SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2516 * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2517 SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2518 )
2519{
2520 assert(scip != NULL);
2521 assert(consdata != NULL);
2522 assert(posinf >= 0);
2523 assert(neginf >= 0);
2524 assert(poshuge >= 0);
2525 assert(neghuge >= 0);
2526 assert(maxactivity != NULL);
2527 assert(isrelax != NULL);
2529
2530 /* if we have neg. infinite contributions, the maxactivity is -infty */
2531 if( neginf > 0 )
2532 {
2533 *maxactivity = -SCIPinfinity(scip);
2535 *isrelax = FALSE;
2536 }
2537 /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2538 else if( posinf > 0 )
2539 {
2540 *maxactivity = SCIPinfinity(scip);
2542 *isrelax = FALSE;
2543 }
2544 /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2545 else if( poshuge > 0 )
2546 {
2547 *maxactivity = SCIPinfinity(scip);
2549 *isrelax = TRUE;
2550 }
2551 /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2552 else if( !goodrelax && neghuge > 0 )
2553 {
2554 *maxactivity = SCIPinfinity(scip);
2556 *isrelax = TRUE;
2557 }
2558 else
2559 {
2560 SCIP_Real tmpactivity;
2561
2562 /* recompute maxactivity if it is not valid */
2563 if( global )
2564 {
2565 if( !consdata->validglbmaxact )
2567 assert(consdata->validglbmaxact);
2568
2569 tmpactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2570 }
2571 else
2572 {
2573 if( !consdata->validmaxact )
2575 assert(consdata->validmaxact);
2576
2577 tmpactivity = QUAD_TO_DBL(consdata->maxactivity);
2578 }
2579
2580 /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2581 * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2582 * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2583 */
2584 if( neghuge > 0 )
2585 {
2586 *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2588 *isrelax = TRUE;
2589 }
2590 /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2591 else
2592 {
2593 *maxactivity = tmpactivity - delta;
2595 *isrelax = FALSE;
2596 }
2597 }
2598}
2599
2600/** gets activity bounds for constraint */
2601static
2603 SCIP* scip, /**< SCIP data structure */
2604 SCIP_CONSDATA* consdata, /**< linear constraint */
2605 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2606 * relaxed activities ignored, anyway? */
2607 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2608 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2609 SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2610 * i.e. <= the exact minactivity (in case of huge contributions),
2611 * or equal to the exact minimal activity */
2612 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2613 * i.e. >= the exact maxactivity (in case of huge contributions),
2614 * or equal to the exact maximal activity */
2615 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2616 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2617
2618 )
2619{
2620 assert(scip != NULL);
2621 assert(consdata != NULL);
2622 assert(minactivity != NULL);
2623 assert(maxactivity != NULL);
2626
2627 if( !consdata->validactivities )
2628 {
2629 consdataCalcActivities(scip, consdata);
2630 assert(consdata->validminact);
2631 assert(consdata->validmaxact);
2632 }
2633 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2634 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2635 assert(consdata->minactivityneginf >= 0);
2636 assert(consdata->minactivityposinf >= 0);
2637 assert(consdata->maxactivityneginf >= 0);
2638 assert(consdata->maxactivityposinf >= 0);
2639
2640 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2641 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2642 minactivity, minisrelax, isminsettoinfinity);
2643
2644 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2645 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2646 maxactivity, maxisrelax, ismaxsettoinfinity);
2647}
2648
2649/** calculates activity bounds for constraint after setting variable to zero */
2650static
2652 SCIP* scip, /**< SCIP data structure */
2653 SCIP_CONSDATA* consdata, /**< linear constraint */
2654 SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2655 SCIP_Real* resactivity, /**< pointer to store the residual activity */
2656 SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2657 SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2658 )
2659{
2660 SCIP_VAR* var;
2661 SCIP_Real val;
2662 SCIP_Real lb;
2663 SCIP_Real ub;
2664 int v;
2665
2666 assert(scip != NULL);
2667 assert(consdata != NULL);
2668 assert(cancelvar != NULL);
2670
2671 *resactivity = 0.0;
2672
2673 for( v = 0; v < consdata->nvars; ++v )
2674 {
2675 var = consdata->vars[v];
2676 assert(var != NULL);
2677 if( var == cancelvar )
2678 continue;
2679
2680 val = consdata->vals[v];
2681
2682 if( useglobalbounds )
2683 {
2684 lb = SCIPvarGetLbGlobal(var);
2685 ub = SCIPvarGetUbGlobal(var);
2686 }
2687 else
2688 {
2689 lb = SCIPvarGetLbLocal(var);
2690 ub = SCIPvarGetUbLocal(var);
2691 }
2692
2693 assert(!SCIPisZero(scip, val));
2694 assert(SCIPisLE(scip, lb, ub));
2695
2696 if( val > 0.0 )
2697 {
2698 if( isminresact )
2699 {
2700 assert(!SCIPisInfinity(scip, -lb));
2701 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2702 *resactivity += val*lb;
2703 }
2704 else
2705 {
2706 assert(!SCIPisInfinity(scip, ub));
2707 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2708 *resactivity += val*ub;
2709 }
2710 }
2711 else
2712 {
2713 if( isminresact)
2714 {
2715 assert(!SCIPisInfinity(scip, ub));
2716 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2717 *resactivity += val*ub;
2718 }
2719 else
2720 {
2721 assert(!SCIPisInfinity(scip, -lb));
2722 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2723 *resactivity += val*lb;
2724 }
2725 }
2726 }
2728}
2729
2730/** gets activity bounds for constraint after setting variable to zero */
2731static
2733 SCIP* scip, /**< SCIP data structure */
2734 SCIP_CONSDATA* consdata, /**< linear constraint */
2735 SCIP_VAR* var, /**< variable to calculate activity residual for */
2736 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2737 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2738 * relaxed acticities ignored, anyway? */
2739 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2740 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2741 SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2742 * relaxation, i.e. <= the exact residual minactivity (in case of huge
2743 * contributions), or equal to the exact residual minactivity */
2744 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2745 * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2746 * contributions), or equal to the exact residual minactivity */
2747 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2748 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2749 )
2750{
2751 SCIP_Real minactbound;
2752 SCIP_Real maxactbound;
2753 SCIP_Real absval;
2754
2755 assert(scip != NULL);
2756 assert(consdata != NULL);
2757 assert(var != NULL);
2764
2765 /* get activity bounds of linear constraint */
2766 if( !consdata->validactivities )
2767 {
2768 consdataCalcActivities(scip, consdata);
2769 assert(consdata->validminact);
2770 assert(consdata->validmaxact);
2771 }
2772 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2773 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2774 assert(consdata->minactivityneginf >= 0);
2775 assert(consdata->minactivityposinf >= 0);
2776 assert(consdata->maxactivityneginf >= 0);
2777 assert(consdata->maxactivityposinf >= 0);
2778 assert(consdata->minactivityneghuge >= 0);
2779 assert(consdata->minactivityposhuge >= 0);
2780 assert(consdata->maxactivityneghuge >= 0);
2781 assert(consdata->maxactivityposhuge >= 0);
2782
2783 if( val > 0.0 )
2784 {
2787 absval = val;
2788 }
2789 else
2790 {
2793 absval = -val;
2794 }
2795
2796 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2797 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2798 */
2800 {
2801 assert(consdata->minactivityposinf >= 1);
2802
2803 getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2804 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2806 }
2807 else if( SCIPisInfinity(scip, -minactbound) )
2808 {
2809 assert(consdata->minactivityneginf >= 1);
2810
2811 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2812 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2814 }
2815 else if( SCIPisHugeValue(scip, minactbound * absval) )
2816 {
2817 assert(consdata->minactivityposhuge >= 1);
2818
2819 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2820 consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2822 }
2823 else if( SCIPisHugeValue(scip, -minactbound * absval) )
2824 {
2825 assert(consdata->minactivityneghuge >= 1);
2826
2827 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2828 consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2830 }
2831 else
2832 {
2833 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2834 consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2836 }
2837
2838 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2839 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2840 */
2842 {
2843 assert(consdata->maxactivityneginf >= 1);
2844
2845 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2846 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2848 }
2849 else if( SCIPisInfinity(scip, maxactbound) )
2850 {
2851 assert(consdata->maxactivityposinf >= 1);
2852
2853 getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2854 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2856 }
2857 else if( SCIPisHugeValue(scip, absval * maxactbound) )
2858 {
2859 assert(consdata->maxactivityposhuge >= 1);
2860
2861 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2862 consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2864 }
2865 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2866 {
2867 assert(consdata->maxactivityneghuge >= 1);
2868
2869 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2870 consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2872 }
2873 else
2874 {
2875 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2876 consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2878 }
2879}
2880
2881/** gets global activity bounds for constraint */
2882static
2884 SCIP* scip, /**< SCIP data structure */
2885 SCIP_CONSDATA* consdata, /**< linear constraint */
2886 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2887 * relaxed acticities ignored, anyway? */
2888 SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2889 SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2890 SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2891 * i.e. <= the exact minactivity (in case of huge contributions),
2892 * or equal to the exact minimal activity */
2893 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2894 * i.e. >= the exact maxactivity (in case of huge contributions),
2895 * or equal to the exact maximal activity */
2896 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2897 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2898 )
2899{
2900 assert(scip != NULL);
2901 assert(consdata != NULL);
2904
2905 if( !consdata->validactivities )
2906 {
2907 consdataCalcActivities(scip, consdata);
2908 assert(consdata->validglbminact);
2909 assert(consdata->validglbmaxact);
2910 }
2911 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2912 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2913 assert(consdata->glbminactivityneginf >= 0);
2914 assert(consdata->glbminactivityposinf >= 0);
2915 assert(consdata->glbmaxactivityneginf >= 0);
2916 assert(consdata->glbmaxactivityposinf >= 0);
2917 assert(consdata->glbminactivityneghuge >= 0);
2918 assert(consdata->glbminactivityposhuge >= 0);
2919 assert(consdata->glbmaxactivityneghuge >= 0);
2920 assert(consdata->glbmaxactivityposhuge >= 0);
2921
2922 if( glbminactivity != NULL )
2923 {
2926
2927 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2928 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2930 }
2931
2932 if( glbmaxactivity != NULL )
2933 {
2936
2937 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2938 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2940 }
2941}
2942
2943/** gets global activity bounds for constraint after setting variable to zero */
2944static
2946 SCIP* scip, /**< SCIP data structure */
2947 SCIP_CONSDATA* consdata, /**< linear constraint */
2948 SCIP_VAR* var, /**< variable to calculate activity residual for */
2949 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2950 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2951 * relaxed acticities ignored, anyway? */
2952 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2953 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2954 SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2955 * relaxation, i.e. <= the exact residual minactivity (in case of huge
2956 * contributions), or equal to the exact residual minactivity */
2957 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2958 * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2959 * contributions), or equal to the exact residual minactivity */
2960 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2961 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2962 )
2963{
2964 SCIP_Real minactbound;
2965 SCIP_Real maxactbound;
2966 SCIP_Real absval;
2967
2968 assert(scip != NULL);
2969 assert(consdata != NULL);
2970 assert(var != NULL);
2973
2974 /* get activity bounds of linear constraint */
2975 if( !consdata->validactivities )
2976 consdataCalcActivities(scip, consdata);
2977
2978 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2979 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2980 assert(consdata->glbminactivityneginf >= 0);
2981 assert(consdata->glbminactivityposinf >= 0);
2982 assert(consdata->glbmaxactivityneginf >= 0);
2983 assert(consdata->glbmaxactivityposinf >= 0);
2984
2985 if( val > 0.0 )
2986 {
2989 absval = val;
2990 }
2991 else
2992 {
2995 absval = -val;
2996 }
2997
2998 if( minresactivity != NULL )
2999 {
3002
3003 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
3004 * and contribution of variable set to zero that has to be subtracted from finite part of activity
3005 */
3007 {
3008 assert(consdata->glbminactivityposinf >= 1);
3009
3010 getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
3011 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3013 }
3014 else if( SCIPisInfinity(scip, -minactbound) )
3015 {
3016 assert(consdata->glbminactivityneginf >= 1);
3017
3018 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
3019 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3021 }
3022 else if( SCIPisHugeValue(scip, minactbound * absval) )
3023 {
3024 assert(consdata->glbminactivityposhuge >= 1);
3025
3026 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3027 consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3029 }
3030 else if( SCIPisHugeValue(scip, -minactbound * absval) )
3031 {
3032 assert(consdata->glbminactivityneghuge >= 1);
3033
3034 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3035 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
3037 }
3038 else
3039 {
3040 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3041 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
3043 }
3044 }
3045
3046 if( maxresactivity != NULL )
3047 {
3050
3051 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
3052 * and contribution of variable set to zero that has to be subtracted from finite part of activity
3053 */
3055 {
3056 assert(consdata->glbmaxactivityneginf >= 1);
3057
3058 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
3059 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3061 }
3062 else if( SCIPisInfinity(scip, maxactbound) )
3063 {
3064 assert(consdata->glbmaxactivityposinf >= 1);
3065
3066 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
3067 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3069 }
3070 else if( SCIPisHugeValue(scip, absval * maxactbound) )
3071 {
3072 assert(consdata->glbmaxactivityposhuge >= 1);
3073
3074 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3075 consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3077 }
3078 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3079 {
3080 assert(consdata->glbmaxactivityneghuge >= 1);
3081
3082 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3083 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3085 }
3086 else
3087 {
3088 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3089 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3091 }
3092 }
3093}
3094
3095/** calculates the activity of the linear constraint for given solution */
3096static
3098 SCIP* scip, /**< SCIP data structure */
3099 SCIP_CONSDATA* consdata, /**< linear constraint data */
3100 SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3101 )
3102{
3103 SCIP_Real activity;
3104
3105 assert(scip != NULL);
3106 assert(consdata != NULL);
3107
3108 if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3109 activity = consdataComputePseudoActivity(scip, consdata);
3110 else
3111 {
3112 SCIP_Real solval;
3113 int nposinf;
3114 int nneginf;
3115 SCIP_Bool negsign;
3116 int v;
3117
3118 activity = 0.0;
3119 nposinf = 0;
3120 nneginf = 0;
3121
3122 for( v = 0; v < consdata->nvars; ++v )
3123 {
3124 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3125
3126 if( consdata->vals[v] < 0 )
3127 negsign = TRUE;
3128 else
3129 negsign = FALSE;
3130
3131 if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3132 ++nposinf;
3133 else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3134 ++nneginf;
3135 else
3136 activity += consdata->vals[v] * solval;
3137 }
3138 assert(nneginf >= 0 && nposinf >= 0);
3139
3140 SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3141
3142 /* check for amount of infinity values and correct the activity */
3143 if( nposinf > 0 && nneginf > 0 )
3144 activity = (consdata->rhs + consdata->lhs) / 2;
3145 else if( nposinf > 0 )
3146 activity = SCIPinfinity(scip);
3147 else if( nneginf > 0 )
3148 activity = -SCIPinfinity(scip);
3149
3150 SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3151 }
3152
3153 if( activity == SCIP_INVALID ) /*lint !e777*/
3154 return activity;
3155 else if( activity < 0 )
3156 activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3157 else
3158 activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3159
3160 return activity;
3161}
3162
3163/** calculates the feasibility of the linear constraint for given solution */
3164static
3166 SCIP* scip, /**< SCIP data structure */
3167 SCIP_CONSDATA* consdata, /**< linear constraint data */
3168 SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3169 )
3170{
3171 SCIP_Real activity;
3172
3173 assert(scip != NULL);
3174 assert(consdata != NULL);
3175
3176 activity = consdataGetActivity(scip, consdata, sol);
3177
3178 if( activity == SCIP_INVALID ) /*lint !e777*/
3179 return -SCIPinfinity(scip);
3180
3181 return MIN(consdata->rhs - activity, activity - consdata->lhs);
3182}
3183
3184/** updates bit signatures after adding a single coefficient */
3185static
3187 SCIP_CONSDATA* consdata, /**< linear constraint data */
3188 int pos /**< position of coefficient to update signatures for */
3189 )
3190{
3191 uint64_t varsignature;
3192 SCIP_Real lb;
3193 SCIP_Real ub;
3194 SCIP_Real val;
3195
3196 assert(consdata != NULL);
3197 assert(consdata->validsignature);
3198
3199 varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3200 lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3201 ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3202 val = consdata->vals[pos];
3203 if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3204 consdata->possignature |= varsignature;
3205 if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3206 consdata->negsignature |= varsignature;
3207}
3208
3209/** calculates the bit signatures of the given constraint data */
3210static
3212 SCIP_CONSDATA* consdata /**< linear constraint data */
3213 )
3214{
3215 assert(consdata != NULL);
3216
3217 if( !consdata->validsignature )
3218 {
3219 int i;
3220
3221 consdata->validsignature = TRUE;
3222 consdata->possignature = 0;
3223 consdata->negsignature = 0;
3224 for( i = 0; i < consdata->nvars; ++i )
3225 consdataUpdateSignatures(consdata, i);
3226 }
3227}
3228
3229/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3230static
3232{ /*lint --e{715}*/
3233 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3234 SCIP_VAR* var1;
3235 SCIP_VAR* var2;
3236
3237 assert(consdata != NULL);
3240
3241 var1 = consdata->vars[ind1];
3242 var2 = consdata->vars[ind2];
3243
3244 /* exactly one variable is binary */
3246 {
3247 return (SCIPvarIsBinary(var1) ? -1 : +1);
3248 }
3249 /* both variables are binary */
3250 else if( SCIPvarIsBinary(var1) )
3251 {
3252 return SCIPvarCompare(var1, var2);
3253 }
3254 else
3255 {
3258
3259 if( vartype1 < vartype2 )
3260 return -1;
3261 else if( vartype1 > vartype2 )
3262 return +1;
3263 else
3264 return SCIPvarCompare(var1, var2);
3265 }
3266}
3267
3268/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3269static
3271{ /*lint --e{715}*/
3272 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3273 SCIP_VAR* var1;
3274 SCIP_VAR* var2;
3275
3276 assert(consdata != NULL);
3279
3280 var1 = consdata->vars[ind1];
3281 var2 = consdata->vars[ind2];
3282
3283 /* exactly one variable is binary */
3285 {
3286 return (SCIPvarIsBinary(var1) ? -1 : +1);
3287 }
3288 /* both variables are binary */
3289 else if( SCIPvarIsBinary(var1) )
3290 {
3291 SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3292 SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3293
3294 if( EPSGT(abscoef1, abscoef2, 1e-9) )
3295 return -1;
3296 else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3297 return +1;
3298 else
3300 }
3301 else
3302 {
3305
3306 if( vartype1 < vartype2 )
3307 {
3308 return -1;
3309 }
3310 else if( vartype1 > vartype2 )
3311 {
3312 return +1;
3313 }
3314 else
3315 {
3316 /* both variables are continuous */
3317 if( !SCIPvarIsIntegral(var1) )
3318 {
3321 }
3322 else
3323 {
3324 SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3325 SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3326
3327 if( EPSGT(abscont1, abscont2, 1e-9) )
3328 return -1;
3329 else if( EPSGT(abscont2, abscont1, 1e-9) )
3330 return +1;
3331 else
3333 }
3334 }
3335 }
3336}
3337
3338/** permutes the constraint's variables according to a given permutation. */
3339static
3341 SCIP_CONSDATA* consdata, /**< the constraint data */
3342 int* perm, /**< the target permutation */
3343 int nvars /**< the number of variables */
3344 )
3345{ /*lint --e{715}*/
3346 SCIP_VAR* varv;
3348 SCIP_Real valv;
3349 int v;
3350 int i;
3351 int nexti;
3352
3353 assert(perm != NULL);
3354 assert(consdata != NULL);
3355
3356 /* permute the variables in the linear constraint according to the target permutation */
3357 eventdatav = NULL;
3358 for( v = 0; v < nvars; ++v )
3359 {
3360 if( perm[v] != v )
3361 {
3362 varv = consdata->vars[v];
3363 valv = consdata->vals[v];
3364 if( consdata->eventdata != NULL )
3365 eventdatav = consdata->eventdata[v];
3366 i = v;
3367 do
3368 {
3369 assert(0 <= perm[i] && perm[i] < nvars);
3370 assert(perm[i] != i);
3371 consdata->vars[i] = consdata->vars[perm[i]];
3372 consdata->vals[i] = consdata->vals[perm[i]];
3373 if( consdata->eventdata != NULL )
3374 {
3375 consdata->eventdata[i] = consdata->eventdata[perm[i]];
3376 consdata->eventdata[i]->varpos = i;
3377 }
3378 nexti = perm[i];
3379 perm[i] = i;
3380 i = nexti;
3381 }
3382 while( perm[i] != v );
3383 consdata->vars[i] = varv;
3384 consdata->vals[i] = valv;
3385 if( consdata->eventdata != NULL )
3386 {
3387 consdata->eventdata[i] = eventdatav;
3388 consdata->eventdata[i]->varpos = i;
3389 }
3390 perm[i] = i;
3391 }
3392 }
3393#ifdef SCIP_DEBUG
3394 /* check sorting */
3395 for( v = 0; v < nvars; ++v )
3396 {
3397 assert(perm[v] == v);
3398 assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3399 }
3400#endif
3401}
3402
3403/** sorts linear constraint's variables depending on the stage of the solving process:
3404 * - during PRESOLVING
3405 * sorts variables by binaries, integers, implicit integers, and continuous variables,
3406 * and the variables of the same type by non-decreasing variable index
3407 *
3408 * - during SOLVING
3409 * sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables,
3410 * and binary and integer variables by their global max activity delta (within each group),
3411 * ties within a group are broken by problem index of the variable.
3412 *
3413 * This fastens the propagation time of the constraint handler.
3414 */
3415static
3417 SCIP* scip, /**< SCIP data structure */
3418 SCIP_CONSDATA* consdata /**< linear constraint data */
3419 )
3420{
3421 assert(scip != NULL);
3422 assert(consdata != NULL);
3423
3424 /* check if there are variables for sorting */
3425 if( consdata->nvars <= 1 )
3426 {
3427 consdata->indexsorted = TRUE;
3428 consdata->coefsorted = TRUE;
3429 consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3430 }
3431 else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3432 || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3433 {
3434 int* perm;
3435 int v;
3436
3437 /* get temporary memory to store the sorted permutation */
3438 SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3439
3440 /* call sorting method */
3442 SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3443 else
3444 SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3445
3446 permSortConsdata(consdata, perm, consdata->nvars);
3447
3448 /* free temporary memory */
3449 SCIPfreeBufferArray(scip, &perm);
3450
3452 {
3453 consdata->indexsorted = FALSE;
3454 consdata->coefsorted = TRUE;
3455
3456 /* count binary variables in the sorted vars array */
3457 consdata->nbinvars = 0;
3458 for( v = 0; v < consdata->nvars; ++v )
3459 {
3460 if( SCIPvarIsBinary(consdata->vars[v]) )
3461 ++consdata->nbinvars;
3462 else
3463 break;
3464 }
3465 }
3466 else
3467 {
3468 consdata->indexsorted = TRUE;
3469 consdata->coefsorted = FALSE;
3470 }
3471 }
3472
3473 return SCIP_OKAY;
3474}
3475
3476
3477/*
3478 * local linear constraint handler methods
3479 */
3480
3481/** sets left hand side of linear constraint */
3482static
3484 SCIP* scip, /**< SCIP data structure */
3485 SCIP_CONS* cons, /**< linear constraint */
3486 SCIP_Real lhs /**< new left hand side */
3487 )
3488{
3489 SCIP_CONSDATA* consdata;
3490 SCIP_Bool locked;
3491 int i;
3492
3493 assert(scip != NULL);
3494 assert(cons != NULL);
3495 assert(!SCIPisInfinity(scip, lhs));
3496
3497 /* adjust value to not be smaller than -inf */
3498 if ( SCIPisInfinity(scip, -lhs) )
3499 lhs = -SCIPinfinity(scip);
3500
3501 consdata = SCIPconsGetData(cons);
3502 assert(consdata != NULL);
3503 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3504 assert(!SCIPisInfinity(scip, consdata->lhs));
3505
3506 /* check whether the side is not changed */
3507 if( SCIPisEQ(scip, consdata->lhs, lhs) )
3508 return SCIP_OKAY;
3509
3510 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3511 if( SCIPisEQ(scip, lhs, consdata->rhs) )
3512 {
3513 consdata->rhs = lhs;
3514 assert(consdata->row == NULL);
3515 }
3516
3517 locked = FALSE;
3518 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3519 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3520
3521 /* if necessary, update the rounding locks of variables */
3522 if( locked )
3523 {
3524 if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3525 {
3526 SCIP_VAR** vars;
3527 SCIP_Real* vals;
3528 int v;
3529
3530 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3531 vars = consdata->vars;
3532 vals = consdata->vals;
3533
3534 for( v = 0; v < consdata->nvars; ++v )
3535 {
3536 assert(vars[v] != NULL);
3537 assert(!SCIPisZero(scip, vals[v]));
3538
3539 if( SCIPisPositive(scip, vals[v]) )
3540 {
3541 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3542 }
3543 else
3544 {
3545 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3546 }
3547 }
3548 }
3549 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3550 {
3551 SCIP_VAR** vars;
3552 SCIP_Real* vals;
3553 int v;
3554
3555 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3556 vars = consdata->vars;
3557 vals = consdata->vals;
3558
3559 for( v = 0; v < consdata->nvars; ++v )
3560 {
3561 assert(vars[v] != NULL);
3562 assert(!SCIPisZero(scip, vals[v]));
3563
3564 if( SCIPisPositive(scip, vals[v]) )
3565 {
3567 }
3568 else
3569 {
3571 }
3572 }
3573 }
3574 }
3575
3576 /* 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 */
3577 if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3578 {
3579 consdata->boundstightened = 0;
3580 consdata->presolved = FALSE;
3581 consdata->cliquesadded = FALSE;
3582 consdata->implsadded = FALSE;
3583
3584 /* mark the constraint for propagation */
3585 if( SCIPconsIsTransformed(cons) )
3586 {
3588 }
3589 }
3590
3591 /* set new left hand side and update constraint data */
3592 consdata->lhs = lhs;
3593 consdata->changed = TRUE;
3594 consdata->normalized = FALSE;
3595 consdata->upgradetried = FALSE;
3596 consdata->rangedrowpropagated = 0;
3597
3598 /* update the lhs of the LP row */
3599 if( consdata->row != NULL )
3600 {
3601 SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3602 }
3603
3604 return SCIP_OKAY;
3605}
3606
3607/** sets right hand side of linear constraint */
3608static
3610 SCIP* scip, /**< SCIP data structure */
3611 SCIP_CONS* cons, /**< linear constraint */
3612 SCIP_Real rhs /**< new right hand side */
3613 )
3614{
3615 SCIP_CONSDATA* consdata;
3616 SCIP_Bool locked;
3617 int i;
3618
3619 assert(scip != NULL);
3620 assert(cons != NULL);
3621 assert(!SCIPisInfinity(scip, -rhs));
3622
3623 /* adjust value to not be larger than inf */
3624 if ( SCIPisInfinity(scip, rhs) )
3625 rhs = SCIPinfinity(scip);
3626
3627 consdata = SCIPconsGetData(cons);
3628 assert(consdata != NULL);
3629 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3630 assert(!SCIPisInfinity(scip, -consdata->rhs));
3631
3632 /* check whether the side is not changed */
3633 if( SCIPisEQ(scip, consdata->rhs, rhs) )
3634 return SCIP_OKAY;
3635
3636 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3637 if( SCIPisEQ(scip, rhs, consdata->lhs) )
3638 {
3639 consdata->lhs = rhs;
3640 assert(consdata->row == NULL);
3641 }
3642
3643 locked = FALSE;
3644 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3645 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3646
3647 /* if necessary, update the rounding locks of variables */
3648 if( locked )
3649 {
3651
3652 if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3653 {
3654 SCIP_VAR** vars;
3655 SCIP_Real* vals;
3656 int v;
3657
3658 /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3659 vars = consdata->vars;
3660 vals = consdata->vals;
3661
3662 for( v = 0; v < consdata->nvars; ++v )
3663 {
3664 assert(vars[v] != NULL);
3665 assert(!SCIPisZero(scip, vals[v]));
3666
3667 if( SCIPisPositive(scip, vals[v]) )
3668 {
3669 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3670 }
3671 else
3672 {
3673 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3674 }
3675 }
3676 }
3677 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3678 {
3679 SCIP_VAR** vars;
3680 SCIP_Real* vals;
3681 int v;
3682
3683 /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3684 vars = consdata->vars;
3685 vals = consdata->vals;
3686
3687 for( v = 0; v < consdata->nvars; ++v )
3688 {
3689 assert(vars[v] != NULL);
3690 assert(!SCIPisZero(scip, vals[v]));
3691
3692 if( SCIPisPositive(scip, vals[v]) )
3693 {
3695 }
3696 else
3697 {
3699 }
3700 }
3701 }
3702 }
3703
3704 /* 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 */
3705 if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3706 {
3707 consdata->boundstightened = 0;
3708 consdata->presolved = FALSE;
3709 consdata->cliquesadded = FALSE;
3710 consdata->implsadded = FALSE;
3711
3712 /* mark the constraint for propagation */
3713 if( SCIPconsIsTransformed(cons) )
3714 {
3716 }
3717 }
3718
3719 /* set new right hand side and update constraint data */
3720 consdata->rhs = rhs;
3721 consdata->changed = TRUE;
3722 consdata->normalized = FALSE;
3723 consdata->upgradetried = FALSE;
3724 consdata->rangedrowpropagated = 0;
3725
3726 /* update the rhs of the LP row */
3727 if( consdata->row != NULL )
3728 {
3729 SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3730 }
3731
3732 return SCIP_OKAY;
3733}
3734
3735/** adds coefficient in linear constraint */
3736static
3738 SCIP* scip, /**< SCIP data structure */
3739 SCIP_CONS* cons, /**< linear constraint */
3740 SCIP_VAR* var, /**< variable of constraint entry */
3741 SCIP_Real val /**< coefficient of constraint entry */
3742 )
3743{
3744 SCIP_CONSDATA* consdata;
3745 SCIP_Bool transformed;
3746
3747 assert(scip != NULL);
3748 assert(cons != NULL);
3749 assert(var != NULL);
3750
3751 /* relaxation-only variables must not be used in checked or enforced constraints */
3753
3754 /* ignore coefficient if it is nearly zero */
3755 if( SCIPisZero(scip, val) )
3756 return SCIP_OKAY;
3757
3758 consdata = SCIPconsGetData(cons);
3759 assert(consdata != NULL);
3760
3761 /* are we in the transformed problem? */
3762 transformed = SCIPconsIsTransformed(cons);
3763
3764 /* always use transformed variables in transformed constraints */
3765 if( transformed )
3766 {
3768 }
3769 assert(var != NULL);
3770 assert(transformed == SCIPvarIsTransformed(var));
3771
3772 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3773 consdata->vars[consdata->nvars] = var;
3774 consdata->vals[consdata->nvars] = val;
3775 consdata->nvars++;
3776
3777 /* capture variable */
3779
3780 /* if we are in transformed problem, the variable needs an additional event data */
3781 if( transformed )
3782 {
3783 if( consdata->eventdata != NULL )
3784 {
3785 SCIP_CONSHDLR* conshdlr;
3786 SCIP_CONSHDLRDATA* conshdlrdata;
3787
3788 /* check for event handler */
3789 conshdlr = SCIPconsGetHdlr(cons);
3790 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3791 assert(conshdlrdata != NULL);
3792 assert(conshdlrdata->eventhdlr != NULL);
3793
3794 /* initialize eventdata array */
3795 consdata->eventdata[consdata->nvars-1] = NULL;
3796
3797 /* catch bound change events of variable */
3798 SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3799 }
3800
3801 /* update minimum and maximum activities */
3802 consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3803
3804 /* update maximum activity delta */
3805 if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3806 {
3807 SCIP_Real lb;
3808 SCIP_Real ub;
3809
3810 lb = SCIPvarGetLbLocal(var);
3811 ub = SCIPvarGetUbLocal(var);
3812
3813 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3814 {
3815 consdata->maxactdelta = SCIPinfinity(scip);
3816 consdata->maxactdeltavar = var;
3817 }
3818 else
3819 {
3820 SCIP_Real domain = ub - lb;
3821 SCIP_Real delta = REALABS(val) * domain;
3822
3823 if( delta > consdata->maxactdelta )
3824 {
3825 consdata->maxactdelta = delta;
3826 consdata->maxactdeltavar = var;
3827 }
3828 }
3829 }
3830 }
3831
3832 /* install rounding locks for new variable */
3833 SCIP_CALL( lockRounding(scip, cons, var, val) );
3834
3835 /* mark the constraint for propagation */
3836 if( transformed )
3837 {
3839 }
3840
3841 consdata->boundstightened = 0;
3842 consdata->presolved = FALSE;
3843 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3844
3845 if( consdata->validsignature )
3846 consdataUpdateSignatures(consdata, consdata->nvars-1);
3847
3848 consdata->changed = TRUE;
3849 consdata->normalized = FALSE;
3850 consdata->upgradetried = FALSE;
3851 consdata->cliquesadded = FALSE;
3852 consdata->implsadded = FALSE;
3853 consdata->rangedrowpropagated = 0;
3854
3855 if( consdata->nvars == 1 )
3856 {
3857 consdata->indexsorted = TRUE;
3858 consdata->coefsorted = TRUE;
3859 consdata->merged = TRUE;
3860 }
3861 else
3862 {
3863 consdata->merged = FALSE;
3864
3866 {
3867 consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3868 consdata->coefsorted = FALSE;
3869 }
3870 else
3871 {
3872 consdata->indexsorted = FALSE;
3873 consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3874 }
3875 }
3876
3877 /* update hascontvar and hasnonbinvar flags */
3878 if( consdata->hasnonbinvalid && !consdata->hascontvar )
3879 {
3880 SCIP_VARTYPE vartype = SCIPvarGetType(var);
3881
3882 if( vartype != SCIP_VARTYPE_BINARY )
3883 {
3884 consdata->hasnonbinvar = TRUE;
3885
3886 if( vartype == SCIP_VARTYPE_CONTINUOUS )
3887 consdata->hascontvar = TRUE;
3888 }
3889 }
3890
3891 /* add the new coefficient to the LP row */
3892 if( consdata->row != NULL )
3893 {
3894 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3895 }
3896
3897 return SCIP_OKAY;
3898}
3899
3900/** deletes coefficient at given position from linear constraint data */
3901static
3903 SCIP* scip, /**< SCIP data structure */
3904 SCIP_CONS* cons, /**< linear constraint */
3905 int pos /**< position of coefficient to delete */
3906 )
3907{
3908 SCIP_CONSDATA* consdata;
3909 SCIP_VAR* var;
3910 SCIP_Real val;
3911
3912 assert(scip != NULL);
3913 assert(cons != NULL);
3914
3915 consdata = SCIPconsGetData(cons);
3916 assert(consdata != NULL);
3917 assert(0 <= pos && pos < consdata->nvars);
3918
3919 var = consdata->vars[pos];
3920 val = consdata->vals[pos];
3921 assert(var != NULL);
3922
3923 /* remove rounding locks for deleted variable */
3924 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3925
3926 /* if we are in transformed problem, delete the event data of the variable */
3927 if( SCIPconsIsTransformed(cons) )
3928 {
3929 SCIP_CONSHDLR* conshdlr;
3930 SCIP_CONSHDLRDATA* conshdlrdata;
3931
3932 /* check for event handler */
3933 conshdlr = SCIPconsGetHdlr(cons);
3934 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3935 assert(conshdlrdata != NULL);
3936 assert(conshdlrdata->eventhdlr != NULL);
3937
3938 /* drop bound change events of variable */
3939 if( consdata->eventdata != NULL )
3940 {
3941 SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3942 assert(consdata->eventdata[pos] == NULL);
3943 }
3944 }
3945
3946 /* move the last variable to the free slot */
3947 if( pos != consdata->nvars - 1 )
3948 {
3949 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3950 consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3951
3952 if( consdata->eventdata != NULL )
3953 {
3954 consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3955 assert(consdata->eventdata[pos] != NULL);
3956 consdata->eventdata[pos]->varpos = pos;
3957 }
3958
3959 consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3960 consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3961 }
3962 consdata->nvars--;
3963
3964 /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3965 * of the remaining variable, or give exactly 0.0)
3966 */
3967 if( consdata->nvars <= 1 )
3969 else
3970 {
3971 if( SCIPconsIsTransformed(cons) )
3972 {
3973 /* if we are in transformed problem, update minimum and maximum activities */
3974 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3975
3976 /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3977 * delta needs to be recalculated on the next real propagation
3978 */
3979 if( consdata->maxactdeltavar == var )
3980 {
3981 consdata->maxactdelta = SCIP_INVALID;
3982 consdata->maxactdeltavar = NULL;
3983 }
3984 }
3985 }
3986
3987 /* mark the constraint for propagation */
3988 if( SCIPconsIsTransformed(cons) )
3989 {
3991 }
3992
3993 consdata->boundstightened = 0;
3994 consdata->presolved = FALSE;
3995 consdata->validsignature = FALSE;
3996 consdata->changed = TRUE;
3997 consdata->normalized = FALSE;
3998 consdata->upgradetried = FALSE;
3999 consdata->cliquesadded = FALSE;
4000 consdata->implsadded = FALSE;
4001 consdata->rangedrowpropagated = 0;
4002
4003 /* check if hasnonbinvar flag might be incorrect now */
4004 if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
4005 {
4006 consdata->hasnonbinvalid = FALSE;
4007 }
4008
4009 /* delete coefficient from the LP row */
4010 if( consdata->row != NULL )
4011 {
4012 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
4013 }
4014
4015 /* release variable */
4017
4018 return SCIP_OKAY;
4019}
4020
4021/** changes coefficient value at given position of linear constraint data */
4022static
4024 SCIP* scip, /**< SCIP data structure */
4025 SCIP_CONS* cons, /**< linear constraint */
4026 int pos, /**< position of coefficient to delete */
4027 SCIP_Real newval /**< new value of coefficient */
4028 )
4029{
4030 SCIP_CONSDATA* consdata;
4031 SCIP_VAR* var;
4032 SCIP_Real val;
4033 SCIP_Bool locked;
4034 int i;
4035
4036 assert(scip != NULL);
4037 assert(cons != NULL);
4038 assert(!SCIPisZero(scip, newval));
4039
4040 consdata = SCIPconsGetData(cons);
4041 assert(consdata != NULL);
4042 assert(0 <= pos && pos < consdata->nvars);
4043 assert(!SCIPisZero(scip, newval));
4044
4045 var = consdata->vars[pos];
4046 val = consdata->vals[pos];
4047 assert(var != NULL);
4049
4050 locked = FALSE;
4051 for( i = 0; i < NLOCKTYPES && !locked; i++ )
4052 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
4053
4054 /* if necessary, update the rounding locks of the variable */
4055 if( locked && newval * val < 0.0 )
4056 {
4058
4059 /* remove rounding locks for variable with old coefficient */
4060 SCIP_CALL( unlockRounding(scip, cons, var, val) );
4061
4062 /* install rounding locks for variable with new coefficient */
4063 SCIP_CALL( lockRounding(scip, cons, var, newval) );
4064 }
4065
4066 /* change the value */
4067 consdata->vals[pos] = newval;
4068
4069 if( consdata->coefsorted )
4070 {
4071 if( pos > 0 )
4072 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
4073 if( consdata->coefsorted && pos < consdata->nvars - 1 )
4074 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
4075 }
4076
4077 /* update minimum and maximum activities */
4078 if( SCIPconsIsTransformed(cons) )
4079 consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
4080
4081 /* mark the constraint for propagation */
4082 if( SCIPconsIsTransformed(cons) )
4083 {
4085 }
4086
4087 consdata->boundstightened = 0;
4088 consdata->presolved = FALSE;
4089 consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
4090 consdata->changed = TRUE;
4091 consdata->normalized = FALSE;
4092 consdata->upgradetried = FALSE;
4093 consdata->cliquesadded = FALSE;
4094 consdata->implsadded = FALSE;
4095 consdata->rangedrowpropagated = 0;
4096
4097 return SCIP_OKAY;
4098}
4099
4100/** scales a linear constraint with a constant scalar */
4101static
4103 SCIP* scip, /**< SCIP data structure */
4104 SCIP_CONS* cons, /**< linear constraint to scale */
4105 SCIP_Real scalar /**< value to scale constraint with */
4106 )
4107{
4108 SCIP_CONSDATA* consdata;
4109 SCIP_Real newval;
4110 SCIP_Real absscalar;
4111 int i;
4112
4113 assert(scip != NULL);
4114 assert(cons != NULL);
4115
4116 consdata = SCIPconsGetData(cons);
4117 assert(consdata != NULL);
4118 assert(consdata->row == NULL);
4119 assert(!SCIPisEQ(scip, scalar, 1.0));
4120
4121 if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4122 || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4123 {
4124 SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4125 SCIPconsGetName(cons), scalar);
4126
4127 return SCIP_OKAY;
4128 }
4129
4130 /* scale the coefficients */
4131 for( i = consdata->nvars - 1; i >= 0; --i )
4132 {
4133 newval = scalar * consdata->vals[i];
4134
4135 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4136 * flooring down our new value
4137 */
4138 if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4139 newval = SCIPfeasFloor(scip, newval + 0.5);
4140
4141 if( SCIPisZero(scip, newval) )
4142 {
4143 SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4144 consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4145 SCIP_CALL( delCoefPos(scip, cons, i) );
4146 }
4147 else
4148 consdata->vals[i] = newval;
4149 }
4150
4151 /* scale the sides */
4152 if( scalar < 0.0 )
4153 {
4154 SCIP_Real lhs;
4155
4156 lhs = consdata->lhs;
4157 consdata->lhs = -consdata->rhs;
4158 consdata->rhs = -lhs;
4159 }
4160 absscalar = REALABS(scalar);
4161 if( !SCIPisInfinity(scip, -consdata->lhs) )
4162 {
4163 newval = absscalar * consdata->lhs;
4164
4165 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4166 * flooring down our new value
4167 */
4168 if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4169 consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4170 else
4171 consdata->lhs = newval;
4172 }
4173 if( !SCIPisInfinity(scip, consdata->rhs) )
4174 {
4175 newval = absscalar * consdata->rhs;
4176
4177 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4178 * our new value
4179 */
4180 if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4181 consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4182 else
4183 consdata->rhs = newval;
4184 }
4185
4187 consdata->cliquesadded = FALSE;
4188 consdata->implsadded = FALSE;
4189
4190 return SCIP_OKAY;
4191}
4192
4193/** perform deletion of variables in all constraints of the constraint handler */
4194static
4196 SCIP* scip, /**< SCIP data structure */
4197 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4198 SCIP_CONS** conss, /**< array of constraints */
4199 int nconss /**< number of constraints */
4200 )
4201{
4202 SCIP_CONSDATA* consdata;
4203 int i;
4204 int v;
4205
4206 assert(scip != NULL);
4207 assert(conshdlr != NULL);
4208 assert(conss != NULL);
4209 assert(nconss >= 0);
4211
4212 /* iterate over all constraints */
4213 for( i = 0; i < nconss; i++ )
4214 {
4215 consdata = SCIPconsGetData(conss[i]);
4216
4217 /* constraint is marked, that some of its variables were deleted */
4218 if( consdata->varsdeleted )
4219 {
4220 /* iterate over all variables of the constraint and delete them from the constraint */
4221 for( v = consdata->nvars - 1; v >= 0; --v )
4222 {
4223 if( SCIPvarIsDeleted(consdata->vars[v]) )
4224 {
4225 SCIP_CALL( delCoefPos(scip, conss[i], v) );
4226 }
4227 }
4228 consdata->varsdeleted = FALSE;
4229 }
4230 }
4231
4232 return SCIP_OKAY;
4233}
4234
4235
4236/** normalizes a linear constraint with the following rules:
4237 * - if all coefficients have them same absolute value, change them to (-)1.0
4238 * - multiplication with +1 or -1:
4239 * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4240 * if the current rule doesn't determine the sign):
4241 * 1. the right hand side must not be negative
4242 * 2. the right hand side must not be infinite
4243 * 3. the absolute value of the right hand side must be greater than that of the left hand side
4244 * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4245 * 5. multiply with +1
4246 * - rationals to integrals
4247 * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4248 * by the smallest common multiple of all denominators to get integral coefficients.
4249 * Forbid large denominators due to numerical stability.
4250 * - division by greatest common divisor
4251 * If all coefficients are integral, divide them by the greatest common divisor.
4252 */
4253static
4255 SCIP* scip, /**< SCIP data structure */
4256 SCIP_CONS* cons, /**< linear constraint to normalize */
4257 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4258 )
4259{
4260 SCIP_CONSDATA* consdata;
4261 SCIP_Real* vals;
4262 SCIP_Longint scm;
4263 SCIP_Longint nominator;
4264 SCIP_Longint denominator;
4265 SCIP_Longint gcd;
4266 SCIP_Longint maxmult;
4267 SCIP_Real epsilon;
4268 SCIP_Real feastol;
4269 SCIP_Real maxabsval;
4270 SCIP_Real minabsval;
4271 SCIP_Bool success;
4272 SCIP_Bool onlyintegral;
4273 int nvars;
4274 int mult;
4275 int nposcoeffs;
4276 int nnegcoeffs;
4277 int i;
4278
4279 assert(scip != NULL);
4280 assert(cons != NULL);
4281 assert(infeasible != NULL);
4282
4283 *infeasible = FALSE;
4284
4285 /* we must not change a modifiable constraint in any way */
4286 if( SCIPconsIsModifiable(cons) )
4287 return SCIP_OKAY;
4288
4289 /* get constraint data */
4290 consdata = SCIPconsGetData(cons);
4291 assert(consdata != NULL);
4292
4293 /* check, if the constraint is already normalized */
4294 if( consdata->normalized )
4295 return SCIP_OKAY;
4296
4297 /* get coefficient arrays */
4298 vals = consdata->vals;
4299 nvars = consdata->nvars;
4300 assert(nvars == 0 || vals != NULL);
4301
4302 if( nvars == 0 )
4303 {
4304 consdata->normalized = TRUE;
4305 return SCIP_OKAY;
4306 }
4307
4308 assert(vals != NULL);
4309
4310 /* get maximum and minimum absolute coefficient */
4311 maxabsval = consdataGetMaxAbsval(consdata);
4312 minabsval = consdataGetMinAbsval(consdata);
4313
4314 /* return if scaling by maxval will eliminate coefficients */
4315 if( SCIPisZero(scip, minabsval/maxabsval) )
4316 return SCIP_OKAY;
4317
4318 /* check if the maximum absolute coefficient is not near 1.0 */
4319 if( !SCIPisEQ(scip, maxabsval, 1.0) )
4320 {
4321 SCIP_Real scalar;
4322
4323 /* calculate scale of the average minimum and maximum absolute coefficient to 1.0 */
4324 scalar = 2.0 / (minabsval + maxabsval);
4325
4326 /* check if all scaled absolute coefficients are near 1.0 */
4327 if( SCIPisEQ(scip, scalar * maxabsval, 1.0) )
4328 {
4329 SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4331 SCIP_CALL( scaleCons(scip, cons, scalar) );
4332
4333 /* get new consdata information, because scaleCons() might have deleted variables */
4334 vals = consdata->vals;
4335 nvars = consdata->nvars;
4336
4337 assert(nvars == 0 || vals != NULL);
4338 }
4339 }
4340
4341 /* nvars might have changed */
4342 if( nvars == 0 )
4343 {
4344 consdata->normalized = TRUE;
4345 return SCIP_OKAY;
4346 }
4347
4348 assert(vals != NULL);
4349
4350 /* calculate the maximal multiplier for common divisor calculation:
4351 * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4352 * which means, a value of feastol/epsilon should be used as maximal multiplier;
4353 * additionally, we don't want to scale the constraint if this would lead to too
4354 * large coefficients
4355 */
4356 epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4357 feastol = SCIPfeastol(scip);
4358 maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4359
4360 if( !consdata->hasnonbinvalid )
4361 consdataCheckNonbinvar(consdata);
4362
4363 /* get maximum absolute coefficient */
4364 maxabsval = consdataGetMaxAbsval(consdata);
4365
4366 /* if all variables are of integral type we will allow a greater multiplier */
4367 if( !consdata->hascontvar )
4368 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4369 else
4370 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4371
4372 /*
4373 * multiplication with +1 or -1
4374 */
4375 mult = 0;
4376
4377 /* 1. the right hand side must not be negative */
4378 if( SCIPisPositive(scip, consdata->lhs) )
4379 mult = +1;
4380 else if( SCIPisNegative(scip, consdata->rhs) )
4381 mult = -1;
4382
4383 if( mult == 0 )
4384 {
4385 /* 2. the right hand side must not be infinite */
4386 if( SCIPisInfinity(scip, -consdata->lhs) )
4387 mult = +1;
4388 else if( SCIPisInfinity(scip, consdata->rhs) )
4389 mult = -1;
4390 }
4391
4392 if( mult == 0 )
4393 {
4394 /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4395 if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4396 mult = +1;
4397 else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4398 mult = -1;
4399 }
4400
4401 if( mult == 0 )
4402 {
4403 /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4404 nposcoeffs = 0;
4405 nnegcoeffs = 0;
4406 for( i = 0; i < nvars; ++i )
4407 {
4408 if( vals[i] > 0.0 )
4409 nposcoeffs++;
4410 else
4411 nnegcoeffs++;
4412 }
4413 if( nposcoeffs > nnegcoeffs )
4414 mult = +1;
4415 else if( nposcoeffs < nnegcoeffs )
4416 mult = -1;
4417 }
4418
4419 if( mult == 0 )
4420 {
4421 /* 5. multiply with +1 */
4422 mult = +1;
4423 }
4424
4425 assert(mult == +1 || mult == -1);
4426 if( mult == -1 )
4427 {
4428 /* scale the constraint with -1 */
4429 SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4431 SCIP_CALL( scaleCons(scip, cons, -1.0) );
4432
4433 /* scalecons() can delete variables, but scaling with -1 should not do that */
4434 assert(nvars == consdata->nvars);
4435 }
4436
4437 /*
4438 * rationals to integrals
4439 *
4440 * @todo try scaling only on behalf of non-continuous variables
4441 */
4442 success = TRUE;
4443 scm = 1;
4444 for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4445 {
4446 if( !SCIPisIntegral(scip, vals[i]) )
4447 {
4448 /* epsilon has been slightly decreased above - to be on the safe side */
4449 success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4450 if( success )
4452 }
4453 }
4454 assert(scm >= 1);
4455
4456 /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4457 * their greatest common divisor
4458 */
4460 if( scm == 1 )
4461 {
4462 for( i = nvars - 1; i >= 0; --i )
4463 {
4464 if( !SCIPisIntegral(scip, vals[i]) )
4465 {
4467 break;
4468 }
4469 }
4470 }
4471
4472 success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4473 if( success && scm != 1 )
4474 {
4475 /* scale the constraint with the smallest common multiple of all denominators */
4476 SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4478 SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4479
4480 if( consdata->validmaxabsval )
4481 {
4482 consdata->maxabsval *= REALABS((SCIP_Real)scm);
4483 if( !SCIPisIntegral(scip, consdata->maxabsval) )
4484 {
4485 consdata->validmaxabsval = FALSE;
4486 consdata->maxabsval = SCIP_INVALID;
4487 consdataCalcMaxAbsval(consdata);
4488 }
4489 }
4490
4491 if( consdata->validminabsval )
4492 {
4493 consdata->minabsval *= REALABS((SCIP_Real)scm);
4494 if( !SCIPisIntegral(scip, consdata->minabsval) )
4495 {
4496 consdata->validminabsval = FALSE;
4497 consdata->minabsval = SCIP_INVALID;
4498 consdataCalcMinAbsval(consdata);
4499 }
4500 }
4501
4502 /* get new consdata information, because scalecons() might have deleted variables */
4503 vals = consdata->vals;
4504 nvars = consdata->nvars;
4505 assert(nvars == 0 || vals != NULL);
4506 }
4507
4508 /*
4509 * division by greatest common divisor
4510 */
4511 if( success && nvars >= 1 )
4512 {
4513 /* all coefficients are integral: divide them by their greatest common divisor */
4514 assert(SCIPisIntegral(scip, vals[0]));
4515
4516 gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4517 for( i = 1; i < nvars && gcd > 1; ++i )
4518 {
4519 assert(SCIPisIntegral(scip, vals[i]));
4520 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4521 }
4522
4523 if( gcd > 1 )
4524 {
4525 /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4526 if( !consdata->hascontvar && onlyintegral )
4527 {
4528 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4529 {
4530 *infeasible = TRUE;
4531
4532 SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4534
4535 return SCIP_OKAY;
4536 }
4537 }
4538
4539 /* divide the constraint by the greatest common divisor of the coefficients */
4540 SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4542 SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4543
4544 if( consdata->validmaxabsval )
4545 {
4546 consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4547 }
4548 if( consdata->validminabsval )
4549 {
4550 consdata->minabsval /= REALABS((SCIP_Real)gcd);
4551 }
4552 }
4553 }
4554
4555 /* mark constraint to be normalized */
4556 consdata->normalized = TRUE;
4557
4558 SCIPdebugMsg(scip, "normalized constraint:\n");
4560
4561 return SCIP_OKAY;
4562}
4563
4564/** replaces multiple occurrences of a variable by a single coefficient */
4565static
4567 SCIP* scip, /**< SCIP data structure */
4568 SCIP_CONS* cons /**< linear constraint */
4569 )
4570{
4571 SCIP_CONSDATA* consdata;
4572 SCIP_VAR* var;
4573 SCIP_Real valsum;
4574 int v;
4575
4576 assert(scip != NULL);
4577 assert(cons != NULL);
4578
4579 consdata = SCIPconsGetData(cons);
4580 assert(consdata != NULL);
4581
4582 if( consdata->merged )
4583 return SCIP_OKAY;
4584
4585 /* sort the constraint */
4586 SCIP_CALL( consdataSort(scip, consdata) );
4587
4588 /* go backwards through the constraint looking for multiple occurrences of the same variable;
4589 * backward direction is necessary, since delCoefPos() modifies the given position and
4590 * the subsequent ones
4591 */
4592 v = consdata->nvars-1;
4593 while( v >= 1 )
4594 {
4595 var = consdata->vars[v];
4596 if( consdata->vars[v-1] == var )
4597 {
4598 valsum = consdata->vals[v];
4599 do
4600 {
4601 SCIP_CALL( delCoefPos(scip, cons, v) );
4602 --v;
4603 valsum += consdata->vals[v];
4604 }
4605 while( v >= 1 && consdata->vars[v-1] == var );
4606
4607 /* modify the last existing occurrence of the variable */
4608 assert(consdata->vars[v] == var);
4609 if( SCIPisZero(scip, valsum) )
4610 {
4611 SCIP_CALL( delCoefPos(scip, cons, v) );
4612
4613 /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4614 * delta needs to be recalculated on the next real propagation
4615 */
4616 if( consdata->maxactdeltavar == var )
4617 {
4618 consdata->maxactdelta = SCIP_INVALID;
4619 consdata->maxactdeltavar = NULL;
4620 }
4621 }
4622 else
4623 {
4624 SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4625 }
4626 }
4627 --v;
4628 }
4629
4630 consdata->merged = TRUE;
4631
4632 return SCIP_OKAY;
4633}
4634
4635/** replaces all fixed and aggregated variables by their non-fixed counterparts */
4636static
4638 SCIP* scip, /**< SCIP data structure */
4639 SCIP_CONS* cons, /**< linear constraint */
4640 SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4641 * information is not needed; in this case, we apply all fixings
4642 * instead of stopping after the first infeasible one */
4643 )
4644{
4645 SCIP_CONSDATA* consdata;
4646 SCIP_VAR* var;
4648 SCIP_Real val;
4649 SCIP_Real* aggrscalars;
4650 SCIP_Real fixedval;
4651 SCIP_Real aggrconst;
4652 int v;
4653 int naggrvars;
4654 int i;
4655
4656 assert(scip != NULL);
4657 assert(cons != NULL);
4658
4659 if( infeasible != NULL )
4660 *infeasible = FALSE;
4661
4662 consdata = SCIPconsGetData(cons);
4663 assert(consdata != NULL);
4664
4665 if( consdata->eventdata == NULL )
4666 {
4667 SCIP_CONSHDLR* conshdlr;
4668 SCIP_CONSHDLRDATA* conshdlrdata;
4669
4670 conshdlr = SCIPconsGetHdlr(cons);
4671 assert(conshdlr != NULL);
4672
4673 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4674 assert(conshdlrdata != NULL);
4675
4676 /* catch bound change events of variables */
4677 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4678 assert(consdata->eventdata != NULL);
4679 }
4680
4681 if( !consdata->removedfixings )
4682 {
4683 SCIP_Real lhssubtrahend;
4684 SCIP_Real rhssubtrahend;
4685
4686 /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4687 * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4688 */
4689 assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4690
4691 lhssubtrahend = 0.0;
4692 rhssubtrahend = 0.0;
4693
4694 SCIPdebugMsg(scip, "applying fixings:\n");
4696
4697 v = 0;
4698 while( v < consdata->nvars )
4699 {
4700 var = consdata->vars[v];
4701 val = consdata->vals[v];
4703
4704 switch( SCIPvarGetStatus(var) )
4705 {
4707 SCIPerrorMessage("original variable in transformed linear constraint\n");
4708 return SCIP_INVALIDDATA;
4709
4712 ++v;
4713 break;
4714
4718 if( !SCIPisInfinity(scip, -consdata->lhs) )
4719 {
4721 {
4722 if( val * fixedval > 0.0 )
4723 {
4724 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4725 }
4726 else
4727 {
4728 if( infeasible != NULL )
4729 {
4730 /* if lhs gets infinity it means that the problem is infeasible */
4731 *infeasible = TRUE;
4732 return SCIP_OKAY;
4733 }
4734 else
4735 {
4737 }
4738 }
4739 }
4740 else
4741 lhssubtrahend += val * fixedval;
4742 }
4743 if( !SCIPisInfinity(scip, consdata->rhs) )
4744 {
4746 {
4747 if( val * fixedval > 0.0 )
4748 {
4749 if( infeasible != NULL )
4750 {
4751 /* if rhs gets -infinity it means that the problem is infeasible */
4752 *infeasible = TRUE;
4753 return SCIP_OKAY;
4754 }
4755 else
4756 {
4757 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4758 }
4759 }
4760 else
4761 {
4763 }
4764 }
4765 else
4766 rhssubtrahend += val * fixedval;
4767 }
4768 SCIP_CALL( delCoefPos(scip, cons, v) );
4769 break;
4770
4772 {
4774 SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4775 SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4776
4777 assert(activevar != NULL);
4779 assert(activevar != NULL);
4780
4782 {
4784 }
4785
4787 {
4788 if( !SCIPisInfinity(scip, -consdata->lhs) )
4790 if( !SCIPisInfinity(scip, consdata->rhs) )
4792 }
4793
4794 SCIP_CALL( delCoefPos(scip, cons, v) );
4795 break;
4796 }
4799 naggrvars = SCIPvarGetMultaggrNVars(var);
4802 for( i = 0; i < naggrvars; ++i )
4803 {
4804 SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4805 }
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
4819
4820 if( !SCIPisInfinity(scip, -consdata->lhs) )
4821 lhssubtrahend += val * aggrconst;
4822 if( !SCIPisInfinity(scip, consdata->rhs) )
4823 rhssubtrahend += val * aggrconst;
4824
4825 SCIP_CALL( delCoefPos(scip, cons, v) );
4826 break;
4827
4828 default:
4829 SCIPerrorMessage("unknown variable status\n");
4830 SCIPABORT();
4831 return SCIP_INVALIDDATA; /*lint !e527*/
4832 }
4833 }
4834
4835 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4836 {
4837 /* for large numbers that are relatively equal, substraction can lead to cancellation,
4838 * causing wrong fixings of other variables --> better use a real zero here;
4839 * for small numbers, polishing the difference might lead to wrong results -->
4840 * better use the exact difference in this case
4841 */
4842 if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4843 {
4844 SCIP_CALL( chgLhs(scip, cons, 0.0) );
4845 }
4846 else
4847 {
4848 SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4849 }
4850 }
4851 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4852 {
4853 /* for large numbers that are relatively equal, substraction can lead to cancellation,
4854 * causing wrong fixings of other variables --> better use a real zero here;
4855 * for small numbers, polishing the difference might lead to wrong results -->
4856 * better use the exact difference in this case
4857 */
4858 if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4859 {
4860 SCIP_CALL( chgRhs(scip, cons, 0.0) );
4861 }
4862 else
4863 {
4864 SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4865 }
4866 }
4867 consdata->removedfixings = TRUE;
4868
4869 SCIPdebugMsg(scip, "after fixings:\n");
4871
4872 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4873 * to clean up the constraint
4874 */
4875 SCIP_CALL( mergeMultiples(scip, cons) );
4876
4877 SCIPdebugMsg(scip, "after merging:\n");
4879 }
4880 assert(consdata->removedfixings);
4881
4882#ifndef NDEBUG
4883 /* check, if all fixings are applied */
4884 for( v = 0; v < consdata->nvars; ++v )
4885 assert(SCIPvarIsActive(consdata->vars[v]));
4886#endif
4887
4888 return SCIP_OKAY;
4889}
4890
4891/** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4892 * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4893 * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4894 * conflict detecting constraint by using NULL as inferred variable
4895 */
4896static
4898 SCIP* scip, /**< SCIP data structure */
4899 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4900 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4901 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4902 int inferpos, /**< position of the inferred variable in the vars array */
4903 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4904 )
4905{
4906 SCIP_CONSDATA* consdata;
4907 SCIP_VAR** vars;
4908 SCIP_Real* vals;
4909 int nvars;
4910 int i;
4911
4912 assert(scip != NULL);
4913 assert(cons != NULL);
4914
4915 consdata = SCIPconsGetData(cons);
4916
4917 assert(consdata != NULL);
4918
4919 vars = consdata->vars;
4920 vals = consdata->vals;
4921 nvars = consdata->nvars;
4922
4923 assert(vars != NULL || nvars == 0);
4924 assert(vals != NULL || nvars == 0);
4925
4926 assert(-1 <= inferpos && inferpos < nvars);
4927 assert((infervar == NULL) == (inferpos == -1));
4928 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4929
4930 /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4931 * residual value, depending on whether the left or right hand side is responsible for the bound change:
4932 * - if the right hand side is the reason, the minimal residual activity is responsible
4933 * - if the left hand side is the reason, the maximal residual activity is responsible
4934 */
4935
4936 /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4938 {
4939 SCIP_Real minresactivity;
4940 SCIP_Real maxresactivity;
4941 SCIP_Bool minisrelax;
4942 SCIP_Bool maxisrelax;
4943 SCIP_Bool isminsettoinfinity;
4944 SCIP_Bool ismaxsettoinfinity;
4945
4948
4949 /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4950 if( infervar != NULL )
4951 {
4952 assert(vals != NULL); /* for flexelint */
4953 if( reasonisrhs )
4956 else
4959 }
4960 else
4961 {
4962 if( reasonisrhs )
4965 else
4968 }
4969
4970 /* we can only do something clever, if the residual activity is finite and not relaxed */
4971 if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4972 {
4973 SCIP_Real rescap;
4974 SCIP_Bool resactisinf;
4975
4977
4978 /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4979 * than its inferred bound
4980 */
4981 if( infervar != NULL )
4982 {
4983 assert(vals != NULL); /* for flexelint */
4984
4985 if( reasonisrhs )
4986 {
4987 if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4988 {
4991 resactisinf = TRUE;
4992 }
4993 rescap = consdata->rhs - minresactivity;
4994 }
4995 else
4996 {
4997 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4998 {
5001 resactisinf = TRUE;
5002 }
5003 rescap = consdata->lhs - maxresactivity;
5004 }
5005
5006 if( reasonisrhs == (vals[inferpos] > 0.0) )
5007 rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
5008 else
5009 rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
5010 }
5011 else
5012 rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
5013
5014 if( !resactisinf )
5015 {
5016 /* now add bounds as reasons until the residual capacity is exceeded */
5017 for( i = 0; i < nvars; ++i )
5018 {
5019 assert( vars != NULL && vals != NULL ); /* for lint */
5020
5021 /* zero coefficients and the inferred variable can be ignored */
5022 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5023 continue;
5024
5025 /* check if the residual capacity is exceeded */
5028 break;
5029
5030 /* update the residual capacity due to the local bound of this variable */
5031 if( reasonisrhs == (vals[i] > 0.0) )
5032 {
5033 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
5034 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5035 rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
5036 }
5037 else
5038 {
5039 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
5040 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5041 rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
5042 }
5043 }
5044 return SCIP_OKAY;
5045 }
5046 }
5047 }
5048
5049 /* for a bound change on a continuous variable, all locally changed bounds are responsible */
5050 for( i = 0; i < nvars; ++i )
5051 {
5052 assert(vars != NULL); /* for flexelint */
5053 assert(vals != NULL); /* for flexelint */
5054
5055 /* zero coefficients and the inferred variable can be ignored */
5056 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5057 continue;
5058
5059 if( reasonisrhs == (vals[i] > 0.0) )
5060 {
5061 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
5062 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5063 }
5064 else
5065 {
5066 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
5067 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5068 }
5069 }
5070
5071 return SCIP_OKAY;
5072}
5073
5074/** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
5075 * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
5076 * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
5077 */
5078static
5080 SCIP* scip, /**< SCIP data structure */
5081 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5082 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
5083 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5084 int inferpos /**< position of the inferred variable in the vars array, or -1 */
5085 )
5086{
5087 SCIP_CONSDATA* consdata;
5088 SCIP_VAR** vars;
5089 int nvars;
5090 int v;
5091
5092 assert(scip != NULL);
5093 assert(cons != NULL);
5094
5095 consdata = SCIPconsGetData(cons);
5096 assert(consdata != NULL);
5097 vars = consdata->vars;
5098 nvars = consdata->nvars;
5099 assert(vars != NULL || nvars == 0);
5100 assert(-1 <= inferpos && inferpos < nvars);
5101 assert((infervar == NULL) == (inferpos == -1));
5102 assert(inferpos == -1 || vars != NULL);
5103 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5104
5105 /* collect all fixed variables */
5106 for( v = nvars - 1; v >= 0; --v )
5107 {
5108 assert(vars != NULL); /* for flexelint */
5109
5110 /* need to add old bounds before propagation of inferrence variable */
5111 if( vars[v] == infervar )
5112 {
5113 assert(vars[v] != NULL);
5114
5116 {
5117 /* @todo get boundchange index before this last boundchange and correct the index */
5118 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5119 }
5120
5122 {
5123 /* @todo get boundchange index before this last boundchange and correct the index */
5124 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5125 }
5126
5127 continue;
5128 }
5129
5130 /* check for fixed variables */
5131 if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5132 {
5133 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5134 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5135 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5136 }
5137 }
5138
5139 return SCIP_OKAY;
5140}
5141
5142/** add reasoning variables to conflict candidate queue which led to the conflict */
5143static
5145 SCIP* scip, /**< SCIP data structure */
5146 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5147 int nvars, /**< number of variables reasoning the infeasibility */
5148 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5149 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5150 )
5151{
5152 int v;
5153
5154 assert(scip != NULL);
5155
5156 /* collect all variables for which the local bounds differ from their global bounds */
5157 for( v = nvars - 1; v >= 0; --v )
5158 {
5159 assert(vars != NULL);
5160
5161 /* check for local bound changes variables */
5163 {
5164 /* add conflict bound */
5166 }
5167
5169 {
5171 }
5172 }
5173
5174 if( var != NULL )
5175 {
5176 if( bound < SCIPvarGetLbLocal(var) )
5177 {
5179 }
5180
5181 if( bound > SCIPvarGetUbLocal(var) )
5182 {
5184 }
5185 }
5186
5187 return SCIP_OKAY;
5188}
5189
5190/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5191 * propagation rule (see propagateCons()):
5192 * (1) activity residuals of all other variables tighten bounds of single variable
5193 */
5194static
5196 SCIP* scip, /**< SCIP data structure */
5197 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5198 SCIP_VAR* infervar, /**< variable that was deduced */
5199 INFERINFO inferinfo, /**< inference information */
5200 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5201 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5202 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5203 )
5204{
5205 SCIP_CONSDATA* consdata;
5206 SCIP_VAR** vars;
5207#ifndef NDEBUG
5208 SCIP_Real* vals;
5209#endif
5210 int nvars;
5211 int inferpos;
5212
5213 assert(scip != NULL);
5214 assert(cons != NULL);
5215 assert(result != NULL);
5216
5217 consdata = SCIPconsGetData(cons);
5218 assert(consdata != NULL);
5219 vars = consdata->vars;
5220 nvars = consdata->nvars;
5221#ifndef NDEBUG
5222 vals = consdata->vals;
5223 assert(vars != NULL);
5224 assert(vals != NULL);
5225#endif
5226
5227 /* get the position of the inferred variable in the vars array */
5228 inferpos = inferInfoGetPos(inferinfo);
5229 if( inferpos >= nvars || vars[inferpos] != infervar )
5230 {
5231 /* find inference variable in constraint */
5232 /**@todo use a binary search here; the variables can be sorted by variable index */
5233 for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5234 {}
5235 }
5238 assert(!SCIPisZero(scip, vals[inferpos]));
5239
5240 switch( inferInfoGetProprule(inferinfo) )
5241 {
5242 case PROPRULE_1_RHS:
5243 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5244 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5245 * domain in order to not exceed the right hand side of the inequality
5246 */
5247 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5248 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5250 break;
5251
5252 case PROPRULE_1_LHS:
5253 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5254 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5255 * domain in order to not fall below the left hand side of the inequality
5256 */
5257 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5258 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5260 break;
5261
5263 /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5264 * the given inference variable to their bounds in this given ranged row
5265 */
5266
5267 /* check that we really have a ranged row here */
5268 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5269 SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5271 break;
5272
5273 case PROPRULE_INVALID:
5274 default:
5275 SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5276 inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5277 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5278 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5279 SCIPinfoMessage(scip, NULL, ";\n");
5280 return SCIP_INVALIDDATA;
5281 }
5282
5283 return SCIP_OKAY;
5284}
5285
5286/** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5287static
5289 SCIP* scip, /**< SCIP data structure */
5290 SCIP_CONS* cons, /**< conflict detecting constraint */
5291 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5292 )
5293{
5294 /* conflict analysis can only be applied in solving stage and if it is turned on */
5296 return SCIP_OKAY;
5297
5298 /* initialize conflict analysis */
5300
5301 /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5303
5304 /* analyze the conflict */
5306
5307 return SCIP_OKAY;
5308}
5309
5310/** check if there is any hope of tightening some bounds */
5311static
5313 SCIP_CONS* cons /**< linear constraint */
5314 )
5315{
5316 SCIP_CONSDATA* consdata;
5317 int infcountmin;
5318 int infcountmax;
5319
5320 consdata = SCIPconsGetData(cons);
5321 assert(consdata != NULL);
5322
5323 infcountmin = consdata->minactivityneginf
5324 + consdata->minactivityposinf
5325 + consdata->minactivityneghuge
5326 + consdata->minactivityposhuge;
5327 infcountmax = consdata->maxactivityneginf
5328 + consdata->maxactivityposinf
5329 + consdata->maxactivityneghuge
5330 + consdata->maxactivityposhuge;
5331
5332 if( infcountmin > 1 && infcountmax > 1 )
5333 return FALSE;
5334
5335 return TRUE;
5336}
5337
5338/** tighten upper bound */
5339static
5341 SCIP* scip, /**< SCIP data structure */
5342 SCIP_CONS* cons, /**< linear constraint */
5343 int pos, /**< variable position */
5344 PROPRULE proprule, /**< propagation rule that deduced the value */
5345 SCIP_Real newub, /**< new upper bound */
5346 SCIP_Real oldub, /**< old upper bound */
5347 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5348 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5349 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5350 )
5351{
5352 SCIP_CONSDATA* consdata;
5353 SCIP_VAR* var;
5354 SCIP_Real lb;
5355 SCIP_Bool infeasible;
5356 SCIP_Bool tightened;
5357
5358 assert(cons != NULL);
5360
5361 consdata = SCIPconsGetData(cons);
5362 assert(consdata != NULL);
5363 var = consdata->vars[pos];
5364 assert(var != NULL);
5365
5366 lb = SCIPvarGetLbLocal(var);
5368
5369 if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5370 {
5371 SCIP_VARTYPE vartype;
5372
5373 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5374 SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5375 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5376
5377 vartype = SCIPvarGetType(var);
5378
5379 /* tighten upper bound */
5380 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5381
5382 if( infeasible )
5383 {
5384 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5386
5387 /* analyze conflict */
5389
5390 *cutoff = TRUE;
5391 }
5392 else if( tightened )
5393 {
5395 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5397
5398 (*nchgbds)++;
5399
5400 /* if variable type was changed we might be able to upgrade the constraint */
5401 if( vartype != SCIPvarGetType(var) )
5402 consdata->upgradetried = FALSE;
5403 }
5404 }
5405 return SCIP_OKAY;
5406}
5407
5408/** tighten lower bound */
5409static
5411 SCIP* scip, /**< SCIP data structure */
5412 SCIP_CONS* cons, /**< linear constraint */
5413 int pos, /**< variable position */
5414 PROPRULE proprule, /**< propagation rule that deduced the value */
5415 SCIP_Real newlb, /**< new lower bound */
5416 SCIP_Real oldlb, /**< old lower bound */
5417 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5418 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5419 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5420 )
5421{
5422 SCIP_CONSDATA* consdata;
5423 SCIP_VAR* var;
5424 SCIP_Real ub;
5425 SCIP_Bool infeasible;
5426 SCIP_Bool tightened;
5427
5428 assert(cons != NULL);
5430
5431 consdata = SCIPconsGetData(cons);
5432 assert(consdata != NULL);
5433 var = consdata->vars[pos];
5434 assert(var != NULL);
5435
5436 ub = SCIPvarGetUbLocal(var);
5438
5439 if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5440 {
5441 SCIP_VARTYPE vartype;
5442
5443 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5444 SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5445 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5446
5447 vartype = SCIPvarGetType(var);
5448
5449 /* tighten lower bound */
5450 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5451
5452 if( infeasible )
5453 {
5454 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5456
5457 /* analyze conflict */
5459
5460 *cutoff = TRUE;
5461 }
5462 else if( tightened )
5463 {
5465 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5467
5468 (*nchgbds)++;
5469
5470 /* if variable type was changed we might be able to upgrade the constraint */
5471 if( vartype != SCIPvarGetType(var) )
5472 consdata->upgradetried = FALSE;
5473 }
5474 }
5475 return SCIP_OKAY;
5476}
5477
5478/** tightens bounds of a single variable due to activity bounds (easy case) */
5479static
5481 SCIP* scip, /**< SCIP data structure */
5482 SCIP_CONS* cons, /**< linear constraint */
5483 int pos, /**< position of the variable in the vars array */
5484 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5485 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5486 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5487 )
5488{
5489 SCIP_CONSDATA* consdata;
5490 SCIP_VAR* var;
5491 SCIP_Real val;
5492 SCIP_Real lb;
5493 SCIP_Real ub;
5494 SCIP_Real lhs;
5495 SCIP_Real rhs;
5496
5497 assert(scip != NULL);
5498 assert(cons != NULL);
5499 assert(cutoff != NULL);
5500 assert(nchgbds != NULL);
5501
5502 /* we cannot tighten variables' bounds, if the constraint may be not complete */
5503 if( SCIPconsIsModifiable(cons) )
5504 return SCIP_OKAY;
5505
5506 consdata = SCIPconsGetData(cons);
5507 assert(consdata != NULL);
5508 assert(0 <= pos && pos < consdata->nvars);
5509
5510 *cutoff = FALSE;
5511
5512 var = consdata->vars[pos];
5513 assert(var != NULL);
5514
5515 /* we cannot tighten bounds of multi-aggregated variables */
5517 return SCIP_OKAY;
5518
5519 val = consdata->vals[pos];
5520 lhs = consdata->lhs;
5521 rhs = consdata->rhs;
5522 assert(!SCIPisZero(scip, val));
5523 assert(!SCIPisInfinity(scip, lhs));
5524 assert(!SCIPisInfinity(scip, -rhs));
5525
5526 lb = SCIPvarGetLbLocal(var);
5527 ub = SCIPvarGetUbLocal(var);
5528 assert(SCIPisLE(scip, lb, ub));
5529
5530 /* recompute activities if needed */
5531 if( !consdata->validactivities )
5532 consdataCalcActivities(scip, consdata);
5533 assert(consdata->validactivities);
5534 if( !consdata->validminact )
5536 assert(consdata->validminact);
5537
5538 if( val > 0.0 )
5539 {
5540 /* check, if we can tighten the variable's upper bound */
5541 if( !SCIPisInfinity(scip, rhs) )
5542 {
5543 SCIP_Real slack;
5544 SCIP_Real alpha;
5545
5546 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5547 assert(consdata->validminact);
5548
5549 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5550 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5551 {
5552 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5553 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5554
5555 *cutoff = TRUE;
5556 return SCIP_OKAY;
5557 }
5558
5559 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5560
5561 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5562 * it to zero
5563 */
5564 if( !SCIPisPositive(scip, slack) )
5565 slack = 0.0;
5566
5567 alpha = val * (ub - lb);
5569
5570 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5571 {
5572 SCIP_Real newub;
5573
5574 /* compute new upper bound */
5575 newub = lb + (slack / val);
5576
5577 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5578
5579 if( *cutoff )
5580 {
5581 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5583
5584 return SCIP_OKAY;
5585 }
5586
5587 /* collect the new upper bound which is needed for the lower bound computation */
5588 ub = SCIPvarGetUbLocal(var);
5589 }
5590 }
5591
5592 /* check, if we can tighten the variable's lower bound */
5593 if( !SCIPisInfinity(scip, -lhs) )
5594 {
5595 SCIP_Real slack;
5596 SCIP_Real alpha;
5597
5598 /* make sure the max activity is reliable */
5599 if( !consdata->validmaxact )
5600 {
5602 }
5603 assert(consdata->validmaxact);
5604
5605 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5606 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5607 {
5608 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5609 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5610
5611 *cutoff = TRUE;
5612 return SCIP_OKAY;
5613 }
5614
5615 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5616
5617 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5618 * it to zero
5619 */
5620 if( !SCIPisPositive(scip, slack) )
5621 slack = 0.0;
5622
5623 alpha = val * (ub - lb);
5625
5626 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5627 {
5628 SCIP_Real newlb;
5629
5630 /* compute new lower bound */
5631 newlb = ub - (slack / val);
5632
5633 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5634
5635 if( *cutoff )
5636 {
5637 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5639
5640 return SCIP_OKAY;
5641 }
5642 }
5643 }
5644 }
5645 else
5646 {
5647 /* check, if we can tighten the variable's lower bound */
5648 if( !SCIPisInfinity(scip, rhs) )
5649 {
5650 SCIP_Real slack;
5651 SCIP_Real alpha;
5652
5653 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5654 assert(consdata->validminact);
5655
5656 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5657 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5658 {
5659 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5660 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5661
5662 *cutoff = TRUE;
5663 return SCIP_OKAY;
5664 }
5665
5666 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5667
5668 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5669 * it to zero
5670 */
5671 if( !SCIPisPositive(scip, slack) )
5672 slack = 0.0;
5673
5674 alpha = val * (lb - ub);
5676
5677 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5678 {
5679 SCIP_Real newlb;
5680
5681 /* compute new lower bound */
5682 newlb = ub + slack / val;
5683
5684 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5685
5686 if( *cutoff )
5687 {
5688 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5690
5691 return SCIP_OKAY;
5692 }
5693 /* collect the new lower bound which is needed for the upper bound computation */
5694 lb = SCIPvarGetLbLocal(var);
5695 }
5696 }
5697
5698 /* check, if we can tighten the variable's upper bound */
5699 if( !SCIPisInfinity(scip, -lhs) )
5700 {
5701 SCIP_Real slack;
5702 SCIP_Real alpha;
5703
5704 /* make sure the max activity is reliable */
5705 if( !consdata->validmaxact )
5706 {
5708 }
5709 assert(consdata->validmaxact);
5710
5711 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5712 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5713 {
5714 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5715 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5716
5717 *cutoff = TRUE;
5718 return SCIP_OKAY;
5719 }
5720
5721 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5722
5723 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5724 * it to zero
5725 */
5726 if( !SCIPisPositive(scip, slack) )
5727 slack = 0.0;
5728
5729 alpha = val * (lb - ub);
5731
5732 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5733 {
5734 SCIP_Real newub;
5735
5736 /* compute new upper bound */
5737 newub = lb - (slack / val);
5738
5739 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5740
5741 if( *cutoff )
5742 {
5743 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5745
5746 return SCIP_OKAY;
5747 }
5748 }
5749 }
5750 }
5751
5752 return SCIP_OKAY;
5753}
5754
5755/** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5756static
5758 SCIP* scip, /**< SCIP data structure */
5759 SCIP_CONS* cons, /**< conflict detecting constraint */
5760 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5761 int nvars, /**< number of variables reasoning the infeasibility */
5762 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5763 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5764 )
5765{
5766#ifndef NDEBUG
5767 SCIP_CONSDATA* consdata;
5768
5769 assert(scip != NULL);
5770 assert(cons != NULL);
5771
5772 consdata = SCIPconsGetData(cons);
5773 assert(consdata != NULL);
5774 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5775#endif
5776
5777 /* conflict analysis can only be applied in solving stage and if it is turned on */
5779 return SCIP_OKAY;
5780
5781 /* initialize conflict analysis */
5783
5784 /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5786
5787 /* add reasoning variables to conflict candidate queue which led to the conflict */
5789
5790 /* analyze the conflict */
5792
5793 return SCIP_OKAY;
5794}
5795
5796/** propagate ranged rows
5797 *
5798 * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5799 * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5800 * variables better.
5801 *
5802 * Example:
5803 * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5804 *
5805 * x3 needs to be a multiple of 3, so the instance is infeasible.
5806 *
5807 * Example:
5808 * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5809 *
5810 * The only possible value for x3 is 2, so the variable will be fixed.
5811 *
5812 * @todo add holes if possible
5813 */
5814static
5816 SCIP* scip, /**< SCIP data structure */
5817 SCIP_CONS* cons, /**< linear constraint */
5818 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5819 int* nfixedvars, /**< pointer to count number of fixed variables */
5820 int* nchgbds, /**< pointer to count the number of bound changes */
5821 int* naddconss /**< pointer to count number of added constraints */
5822 )
5823{
5824 SCIP_CONSHDLRDATA* conshdlrdata;
5825 SCIP_CONSHDLR* conshdlr;
5826 SCIP_CONSDATA* consdata;
5828 SCIP_Real* infcheckvals;
5829 SCIP_Real minactinfvars;
5830 SCIP_Real maxactinfvars;
5831 SCIP_Real lb;
5832 SCIP_Real ub;
5833 SCIP_Real feastol;
5834 SCIP_Real fixedact;
5835 SCIP_Real lhs;
5836 SCIP_Real rhs;
5837 SCIP_Real absminbincoef;
5838 SCIP_Longint gcd;
5839 SCIP_Longint gcdtmp;
5840 SCIP_Bool minactinfvarsinvalid;
5841 SCIP_Bool maxactinfvarsinvalid;
5842 SCIP_Bool possiblegcd;
5843 SCIP_Bool gcdisone;
5844 SCIP_Bool addartconss;
5845 int ninfcheckvars;
5846 int nunfixedvars;
5847 int nfixedconsvars;
5848 int ncontvars;
5849 int pos;
5850 int v;
5851
5852 assert(scip != NULL);
5853 assert(cons != NULL);
5854 assert(cutoff != NULL);
5855 assert(nfixedvars != NULL);
5856 assert(nchgbds != NULL);
5857 assert(naddconss != NULL);
5858
5859 /* modifiable constraint can be changed so we do not have all necessary information */
5860 if( SCIPconsIsModifiable(cons) )
5861 return SCIP_OKAY;
5862
5863 consdata = SCIPconsGetData(cons);
5864 assert(consdata != NULL);
5865
5866 /* we already did full ranged row propagation */
5867 if( consdata->rangedrowpropagated == 2 )
5868 return SCIP_OKAY;
5869
5870 /* at least three variables are needed */
5871 if( consdata->nvars < 3 )
5872 return SCIP_OKAY;
5873
5874 /* do nothing on normal inequalities */
5875 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5876 return SCIP_OKAY;
5877
5878 /* get constraint handler data */
5879 conshdlr = SCIPconsGetHdlr(cons);
5880 assert(conshdlr != NULL);
5881 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5882 assert(conshdlrdata != NULL);
5883
5884 addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5885
5886 /* we may add artificial constraints */
5887 if( addartconss )
5888 consdata->rangedrowpropagated = 2;
5889 /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5890 * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5891 * artificial constraints
5892 */
5893 else
5894 {
5895 if( consdata->rangedrowpropagated > 0 )
5896 return SCIP_OKAY;
5897
5898 consdata->rangedrowpropagated = 1;
5899 }
5900 fixedact = 0;
5901 nfixedconsvars = 0;
5902 /* calculate fixed activity and number of fixed variables */
5903 for( v = consdata->nvars - 1; v >= 0; --v )
5904 {
5905 /* all zero coefficients should be eliminated */
5906 assert(!SCIPisZero(scip, consdata->vals[v]));
5907
5908 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5909 {
5910 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5912 }
5913 }
5914
5915 /* do not work with huge fixed activities */
5917 return SCIP_OKAY;
5918
5919 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5921 lhs = consdata->lhs - fixedact;
5922 rhs = consdata->rhs - fixedact;
5923 nunfixedvars = consdata->nvars - nfixedconsvars;
5924
5925 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5928
5930 ncontvars = 0;
5931 gcdisone = TRUE;
5932 possiblegcd = TRUE;
5933
5934 /* we now partition all unfixed variables in two groups:
5935 *
5936 * the first one contains all integral variable with integral
5937 * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5938 * given
5939 *
5940 * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5941 * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5942 */
5943
5944 /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5945 * variables
5946 */
5947 ninfcheckvars = 0;
5948 v = -1;
5949 pos = -1;
5950 do
5951 {
5952 ++v;
5953
5954 /* partition the variables, do not change the order of collection, because it might be used later on */
5955 while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5956 !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5957 {
5958 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5959 {
5960 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5961 {
5962 ++ncontvars;
5963 }
5964 else if( SCIPvarIsBinary(consdata->vars[v]) )
5965 {
5966 SCIP_Real absval;
5967
5968 absval = REALABS(consdata->vals[v]);
5969
5970 if( absminbincoef > absval )
5972 }
5973
5974 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5976 infcheckvars[ninfcheckvars] = consdata->vars[v];
5977 infcheckvals[ninfcheckvars] = consdata->vals[v];
5978 ++ninfcheckvars;
5979
5980 if( pos == -1 )
5981 pos = v;
5982 }
5983 ++v;
5984 }
5985 }
5986 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5987
5988 /* if the first group of variables is empty, we stop */
5989 /* @todo try to propagate/split up a constraint of the form:
5990 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5991 * 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]
5992 */
5993 if( v == consdata->nvars )
5994 goto TERMINATE;
5995
5996 /* we need at least two non-continuous variables */
5997 if( ncontvars + 2 > nunfixedvars )
5998 goto TERMINATE;
5999
6000 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
6001 assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
6002
6003 feastol = SCIPfeastol(scip);
6004
6005 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
6006 assert(gcd >= 2);
6007
6008 /* go on to partition the variables, do not change the order of collection, because it might be used later on;
6009 * calculate gcd over the first part of variables */
6010 for( ; v < consdata->nvars; ++v )
6011 {
6012 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6013 continue;
6014
6015 if( SCIPvarIsBinary(consdata->vars[v]) )
6016 {
6017 SCIP_Real absval;
6018
6019 absval = REALABS(consdata->vals[v]);
6020
6021 if( absminbincoef > absval )
6023 }
6024
6025 if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
6026 SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
6027 {
6028 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
6029 ++ncontvars;
6030
6031 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
6033 infcheckvars[ninfcheckvars] = consdata->vars[v];
6034 infcheckvals[ninfcheckvars] = consdata->vals[v];
6035
6036 ++ninfcheckvars;
6037
6038 if( pos == -1 )
6039 pos = v;
6040 }
6041 else
6042 {
6043 assert(REALABS(consdata->vals[v]) > 1.5);
6044
6045 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
6046 assert(gcdtmp >= 1);
6047
6048 if( gcdtmp == 1 )
6049 {
6050 infcheckvars[ninfcheckvars] = consdata->vars[v];
6051 infcheckvals[ninfcheckvars] = consdata->vals[v];
6052
6053 ++ninfcheckvars;
6054
6055 if( pos == -1 )
6056 pos = v;
6057 }
6058 else
6059 gcd = gcdtmp;
6060 }
6061 }
6062 assert(gcd >= 2);
6063
6064 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
6065 * normalizeCons() */
6066 if( ninfcheckvars == 0 )
6067 goto TERMINATE;
6068
6069 assert(pos >= 0);
6070
6073 maxactinfvars = 0.0;
6074 minactinfvars = 0.0;
6075
6076 /* calculate activities over all infcheckvars */
6077 for( v = ninfcheckvars - 1; v >= 0; --v )
6078 {
6081
6082 if( SCIPisInfinity(scip, -lb) )
6083 {
6084 if( infcheckvals[v] < 0.0 )
6086 else
6088 }
6089 else
6090 {
6091 if( infcheckvals[v] < 0.0 )
6092 maxactinfvars += infcheckvals[v] * lb;
6093 else
6094 minactinfvars += infcheckvals[v] * lb;
6095 }
6096
6097 if( SCIPisInfinity(scip, ub) )
6098 {
6099 if( infcheckvals[v] > 0.0 )
6101 else
6103 }
6104 else
6105 {
6106 if( infcheckvals[v] > 0.0 )
6107 maxactinfvars += infcheckvals[v] * ub;
6108 else
6109 minactinfvars += infcheckvals[v] * ub;
6110 }
6111
6112 /* better abort on to big values */
6117
6119 goto TERMINATE;
6120 }
6122
6123 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6125
6126 /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6127 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6128 * activities */
6129 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6130 * !!!note!!!
6131 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6132 * are not at their global bound
6133 */
6134
6135 /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6136 * infeasibility */
6137 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6138 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6139 {
6140 SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6142
6143 /* start conflict analysis */
6144 /* @todo improve conflict analysis by adding relaxed bounds */
6146
6147 *cutoff = TRUE;
6148 }
6149 else if( ncontvars == 0 )
6150 {
6151 SCIP_Longint gcdinfvars = -1;
6152
6153 /* check for gcd over all infcheckvars */
6154 if( possiblegcd )
6155 {
6156 v = ninfcheckvars - 1;
6157 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6158 assert(gcdinfvars >= 2);
6159
6160 for( ; v >= 0 && gcdinfvars >= 2; --v )
6161 {
6162 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6163 }
6164 }
6165 else if( gcdisone )
6166 gcdinfvars = 1;
6167
6168 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6169
6170 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6171 if( gcdinfvars >= 1 )
6172 {
6173 SCIP_Real value;
6174 SCIP_Real value2;
6175 SCIP_Real minvalue = SCIP_INVALID;
6176 SCIP_Real maxvalue = SCIP_INVALID;
6177 int nsols = 0;
6178
6180
6181 /* check how many possible solutions exist */
6182 while( SCIPisLE(scip, value, maxactinfvars) )
6183 {
6184 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6185
6186 /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6187 if( !SCIPisGE(scip, value2, lhs) )
6188 {
6189 value2 += gcd;
6190 }
6191
6192 if( SCIPisLE(scip, value2, rhs) )
6193 {
6194 ++nsols;
6195
6196 /* early termination if we found more than two solutions */
6197 if( nsols == 3 )
6198 break;
6199
6200 if( minvalue == SCIP_INVALID ) /*lint !e777*/
6201 minvalue = value;
6202
6203 maxvalue = value;
6204 }
6205 value += gcdinfvars;
6206 }
6207 assert(nsols < 2 || minvalue <= maxvalue);
6208
6209 /* determine last possible solution for better bounding */
6210 if( nsols == 3 )
6211 {
6212#ifndef NDEBUG
6213 SCIP_Real secondsolval = maxvalue;
6214#endif
6216
6217 /* check how many possible solutions exist */
6218 while( SCIPisGE(scip, value, minactinfvars) )
6219 {
6220 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6221
6222 /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6223 if( !SCIPisLE(scip, value2, rhs) )
6224 {
6225 value2 -= gcd;
6226 }
6227
6228 if( SCIPisGE(scip, value2, lhs) )
6229 {
6230 maxvalue = value;
6231 assert(maxvalue > minvalue);
6232 break;
6233 }
6234 value -= gcdinfvars;
6235 }
6236 assert(maxvalue > secondsolval);
6237 }
6238
6239 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6240 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6241
6242 /* no possible solution found */
6243 if( nsols == 0 )
6244 {
6245 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6246 gcdinfvars, gcd, lhs, rhs);
6247 SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6249
6250 /* start conflict analysis */
6251 /* @todo improve conflict analysis by adding relaxed bounds */
6253
6254 *cutoff = TRUE;
6255 }
6256 /* if only one solution exist we can extract a new constraint or fix variables */
6257 else if( nsols == 1 )
6258 {
6259 assert(minvalue == maxvalue); /*lint !e777*/
6260
6261 /* we can fix the only variable in our second set of variables */
6262 if( ninfcheckvars == 1 )
6263 {
6264 SCIP_Bool fixed;
6265
6267
6268 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6271
6272 /* fix variable to only possible value */
6275
6276 if( *cutoff )
6277 {
6278 /* start conflict analysis */
6279 /* @todo improve conflict analysis by adding relaxed bounds */
6281 }
6282
6283 if( fixed )
6284 ++(*nfixedvars);
6285 }
6286 else
6287 {
6288 /* check for exactly one unfixed variable which is not part of the infcheckvars */
6289 if( ninfcheckvars == nunfixedvars - 1 )
6290 {
6291 SCIP_Real bound;
6292 SCIP_Bool foundvar = FALSE;
6293 SCIP_Bool fixed;
6294 int w = 0;
6295
6296 assert(ninfcheckvars > 0);
6297
6298 /* find variable which is not an infcheckvar and fix it */
6299 for( v = 0; v < consdata->nvars - 1; ++v )
6300 {
6301 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6302 {
6303 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6304 {
6305#ifndef NDEBUG
6306 int v2 = v + 1;
6307 int w2 = w;
6308
6309 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6310
6311 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6312 {
6313 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6314 continue;
6315
6316 assert(consdata->vars[v2] == infcheckvars[w2]);
6317 ++w2;
6318 }
6320#endif
6321 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6322
6323 foundvar = TRUE;
6324
6325 if( consdata->vals[v] < 0 )
6326 {
6327 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6328 }
6329 else
6330 {
6331 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6332 }
6333
6334 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6335 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6336 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6337
6338 /* fix variable to only possible value */
6339 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6341
6342 if( *cutoff )
6343 {
6344 /* start conflict analysis */
6345 /* @todo improve conflict analysis by adding relaxed bounds */
6347 consdata->vars[v], bound) );
6348 }
6349
6350 if( fixed )
6351 ++(*nfixedvars);
6352
6353 break;
6354 }
6355
6356 ++w;
6357 }
6358 }
6359
6360 /* maybe last variable was the not infcheckvar */
6361 if( !foundvar )
6362 {
6363 assert(v == consdata->nvars - 1);
6364 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6365
6366 if( consdata->vals[v] < 0 )
6367 {
6368 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6369 }
6370 else
6371 {
6372 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6373 }
6374
6375 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6376 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6377 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6378
6379 /* fix variable to only possible value */
6380 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6382
6383 if( *cutoff )
6384 {
6385 /* start conflict analysis */
6386 /* @todo improve conflict analysis by adding relaxed bounds */
6388 consdata->vars[v], bound) );
6389 }
6390
6391 if( fixed )
6392 ++(*nfixedvars);
6393 }
6394 }
6395 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6396 {
6397 /* aggregation possible if we have two variables, but this will be done later on */
6399 char name[SCIP_MAXSTRLEN];
6400
6401 /* create, add, and release new artificial constraint */
6402 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6403 ++conshdlrdata->naddconss;
6404
6405 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6406
6408 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6410
6412
6414
6415 ++(*naddconss);
6416 }
6417 }
6418 }
6419 /* at least two solutions */
6420 else
6421 {
6422 /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6423
6424 /* only one variable in the second set, so we can bound this variables */
6425 if( ninfcheckvars == 1 )
6426 {
6427 SCIP_Bool tightened;
6428 SCIP_Real newlb;
6429 SCIP_Real newub;
6430
6432
6433 if( infcheckvals[0] < 0 )
6434 {
6435 newlb = maxvalue/infcheckvals[0];
6436 newub = minvalue/infcheckvals[0];
6437 }
6438 else
6439 {
6440 newlb = minvalue/infcheckvals[0];
6441 newub = maxvalue/infcheckvals[0];
6442 }
6443 assert(newlb < newub);
6444
6446 {
6447 /* update lower bound of variable */
6448 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6450
6451 /* tighten variable lower bound to minimal possible value */
6453 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6454
6455 if( *cutoff )
6456 {
6457 /* start conflict analysis */
6458 /* @todo improve conflict analysis by adding relaxed bounds */
6460 }
6461
6462 if( tightened )
6463 ++(*nchgbds);
6464 }
6465
6467 {
6468 /* update upper bound of variable */
6469 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6471
6472 /* tighten variable upper bound to maximal possible value */
6474 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6475
6476 if( *cutoff )
6477 {
6478 /* start conflict analysis */
6479 /* @todo improve conflict analysis by adding relaxed bounds */
6481 }
6482
6483 if( tightened )
6484 ++(*nchgbds);
6485 }
6486 }
6487 /* check if we have only one not infcheckvars, if so we can tighten this variable */
6488 else if( ninfcheckvars == nunfixedvars - 1 )
6489 {
6490 SCIP_Bool foundvar = FALSE;
6491 SCIP_Bool tightened;
6492 SCIP_Real newlb;
6493 SCIP_Real newub;
6494 int w = 0;
6495
6496 assert(ninfcheckvars > 0);
6497 assert(minvalue < maxvalue);
6498
6499 /* find variable which is not an infcheckvar and fix it */
6500 for( v = 0; v < consdata->nvars - 1; ++v )
6501 {
6502 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6503 {
6504 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6505 {
6506#ifndef NDEBUG
6507 int v2 = v + 1;
6508 int w2 = w;
6509
6510 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6511
6512 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6513 {
6514 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6515 continue;
6516
6517 assert(consdata->vars[v2] == infcheckvars[w2]);
6518 ++w2;
6519 }
6521#endif
6522
6523 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6524 foundvar = TRUE;
6525
6526 if( consdata->vals[v] < 0 )
6527 {
6528 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6529 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6530 }
6531 else
6532 {
6533 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6534 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6535 }
6537
6538 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6539 {
6540 /* update lower bound of variable */
6541 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6542 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6543
6544 /* tighten variable lower bound to minimal possible value */
6545 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6546 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6547
6548 if( *cutoff )
6549 {
6550 /* start conflict analysis */
6551 /* @todo improve conflict analysis by adding relaxed bounds */
6553 consdata->vars[v], newlb) );
6554 }
6555
6556 if( tightened )
6557 ++(*nchgbds);
6558 }
6559
6560 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6561 {
6562 /* update upper bound of variable */
6563 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6564 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6565
6566 /* tighten variable upper bound to maximal possible value */
6567 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6568 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6569
6570 if( *cutoff )
6571 {
6572 /* start conflict analysis */
6573 /* @todo improve conflict analysis by adding relaxed bounds */
6575 consdata->vars[v], newub) );
6576 }
6577
6578 if( tightened )
6579 ++(*nchgbds);
6580 }
6581
6582 break;
6583 }
6584
6585 ++w;
6586 }
6587 }
6588
6589 /* maybe last variable was the not infcheckvar */
6590 if( !foundvar )
6591 {
6592 assert(v == consdata->nvars - 1);
6593 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6594
6595 if( consdata->vals[v] < 0 )
6596 {
6597 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6598 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6599 }
6600 else
6601 {
6602 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6603 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6604 }
6606
6607 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6608 {
6609 /* update lower bound of variable */
6610 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6611 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6612
6613 /* tighten variable lower bound to minimal possible value */
6614 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6615 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6616
6617 if( *cutoff )
6618 {
6619 /* start conflict analysis */
6620 /* @todo improve conflict analysis by adding relaxed bounds */
6622 }
6623
6624 if( tightened )
6625 ++(*nchgbds);
6626 }
6627
6628 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6629 {
6630 /* update upper bound of variable */
6631 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6632 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6633
6634 /* tighten variable upper bound to maximal possible value */
6635 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6636 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6637
6638 if( *cutoff )
6639 {
6640 /* start conflict analysis */
6641 /* @todo improve conflict analysis by adding relaxed bounds */
6643 }
6644
6645 if( tightened )
6646 ++(*nchgbds);
6647 }
6648 }
6649 }
6650 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6651 * region for our infcheckvars, if possible
6652 */
6653 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6654 {
6656 char name[SCIP_MAXSTRLEN];
6657 SCIP_Real newlhs;
6658 SCIP_Real newrhs;
6659
6660 assert(maxvalue > minvalue);
6661
6662 if( SCIPisGT(scip, minvalue, minactinfvars) )
6663 newlhs = minvalue;
6664 else
6666
6667 if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6668 newrhs = maxvalue;
6669 else
6671
6673 {
6674 /* create, add, and release new artificial constraint */
6675 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6676 ++conshdlrdata->naddconss;
6677
6678 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6679
6683
6686
6687 ++(*naddconss);
6688 }
6689 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6690 * should be maxvalue */
6691 }
6692 }
6693 }
6694 }
6695 else if( addartconss && ncontvars < ninfcheckvars )
6696 {
6697 SCIP_Real maxact = 0.0;
6698 SCIP_Real minact = 0.0;
6699 int w = 0;
6700
6701 /* compute activities of non-infcheckvars */
6702 for( v = 0; v < consdata->nvars; ++v )
6703 {
6705 {
6706 ++w;
6707 continue;
6708 }
6709
6710 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6711 {
6712 if( SCIPvarIsBinary(consdata->vars[v]) )
6713 {
6714 if( consdata->vals[v] > 0.0 )
6715 maxact += consdata->vals[v];
6716 else
6717 minact += consdata->vals[v];
6718 }
6719 else
6720 {
6721 SCIP_Real tmpval;
6722
6723 assert(SCIPvarIsIntegral(consdata->vars[v]));
6724
6725 if( consdata->vals[v] > 0.0 )
6726 {
6727 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6728
6729 if( SCIPisHugeValue(scip, -tmpval) )
6730 break;
6731
6732 minact += tmpval;
6733
6734 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6735
6737 break;
6738
6739 maxact += tmpval;
6740 }
6741 else
6742 {
6743 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6744
6745 if( SCIPisHugeValue(scip, -tmpval) )
6746 break;
6747
6748 minact += tmpval;
6749
6750 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6751
6753 break;
6754
6755 maxact += tmpval;
6756 }
6757 }
6758 }
6759 }
6760 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6761 {
6763 char name[SCIP_MAXSTRLEN];
6764 SCIP_Real newlhs;
6765 SCIP_Real newrhs;
6766
6767 assert(maxact > minact);
6769
6770 newlhs = lhs - maxact;
6771 newrhs = rhs - minact;
6772 assert(newlhs < newrhs);
6773
6774 /* create, add, and release new artificial constraint */
6775 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6776 ++conshdlrdata->naddconss;
6777
6778 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6779
6783
6786
6787 ++(*naddconss);
6788 }
6789 }
6790
6791 TERMINATE:
6794
6795 return SCIP_OKAY;
6796}
6797
6798/** tightens bounds of a single variable due to activity bounds */
6799static
6801 SCIP* scip, /**< SCIP data structure */
6802 SCIP_CONS* cons, /**< linear constraint */
6803 int pos, /**< position of the variable in the vars array */
6804 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6805 int* nchgbds, /**< pointer to count the total number of tightened bounds */
6806 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6807 )
6808{
6809 SCIP_CONSDATA* consdata;
6810 SCIP_VAR* var;
6811 SCIP_Real val;
6812 SCIP_Real lb;
6813 SCIP_Real ub;
6814 SCIP_Real minresactivity;
6815 SCIP_Real maxresactivity;
6816 SCIP_Real lhs;
6817 SCIP_Real rhs;
6818 SCIP_Bool infeasible;
6819 SCIP_Bool tightened;
6820 SCIP_Bool minisrelax;
6821 SCIP_Bool maxisrelax;
6822 SCIP_Bool isminsettoinfinity;
6823 SCIP_Bool ismaxsettoinfinity;
6824
6825 assert(scip != NULL);
6826 assert(cons != NULL);
6827 assert(cutoff != NULL);
6828 assert(nchgbds != NULL);
6829
6830 /* we cannot tighten variables' bounds, if the constraint may be not complete */
6831 if( SCIPconsIsModifiable(cons) )
6832 return SCIP_OKAY;
6833
6834 consdata = SCIPconsGetData(cons);
6835 assert(consdata != NULL);
6836 assert(0 <= pos && pos < consdata->nvars);
6837
6838 *cutoff = FALSE;
6839
6840 var = consdata->vars[pos];
6841
6842 /* we cannot tighten bounds of multi-aggregated variables */
6844 return SCIP_OKAY;
6845
6846 val = consdata->vals[pos];
6847 lhs = consdata->lhs;
6848 rhs = consdata->rhs;
6851 assert(var != NULL);
6852 assert(!SCIPisZero(scip, val));
6853 assert(!SCIPisInfinity(scip, lhs));
6854 assert(!SCIPisInfinity(scip, -rhs));
6855
6856 lb = SCIPvarGetLbLocal(var);
6857 ub = SCIPvarGetUbLocal(var);
6858 assert(SCIPisLE(scip, lb, ub));
6859
6860 if( val > 0.0 )
6861 {
6862 /* check, if we can tighten the variable's bounds */
6864 {
6865 SCIP_Real newub;
6866
6867 newub = (rhs - minresactivity)/val;
6868
6869 if( !SCIPisInfinity(scip, newub) &&
6870 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6871 {
6872 SCIP_Bool activityunreliable;
6873 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6874
6875 /* check minresactivities for reliability */
6876 if( activityunreliable )
6877 {
6879 newub = (rhs - minresactivity)/val;
6882 && (!force || !SCIPisLT(scip, newub, ub)));
6883 }
6884
6885 if( !activityunreliable )
6886 {
6887 /* tighten upper bound */
6888 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6889 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6891 &infeasible, &tightened) );
6892 if( infeasible )
6893 {
6894 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6896
6897 /* analyze conflict */
6899
6900 *cutoff = TRUE;
6901 return SCIP_OKAY;
6902 }
6903 if( tightened )
6904 {
6905 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6907 (*nchgbds)++;
6908
6909 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6910 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6911 }
6912 }
6913 }
6914 }
6915
6916 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6917 {
6918 SCIP_Real newlb;
6919
6920 newlb = (lhs - maxresactivity)/val;
6921 if( !SCIPisInfinity(scip, -newlb) &&
6922 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6923 {
6924 /* check maxresactivities for reliability */
6925 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6926 {
6928 newlb = (lhs - maxresactivity)/val;
6929
6932 && (!force || !SCIPisGT(scip, newlb, lb))) )
6933 return SCIP_OKAY;
6934 }
6935
6936 /* tighten lower bound */
6937 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6938 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6940 &infeasible, &tightened) );
6941 if( infeasible )
6942 {
6943 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6945
6946 /* analyze conflict */
6948
6949 *cutoff = TRUE;
6950 return SCIP_OKAY;
6951 }
6952 if( tightened )
6953 {
6954 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6956 (*nchgbds)++;
6957 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6958 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6959 }
6960 }
6961 }
6962 }
6963 else
6964 {
6965 /* check, if we can tighten the variable's bounds */
6967 {
6968 SCIP_Real newlb;
6969
6970 newlb = (rhs - minresactivity)/val;
6971 if( !SCIPisInfinity(scip, -newlb) &&
6972 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6973 {
6974 SCIP_Bool activityunreliable;
6975 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6976 /* check minresactivities for reliability */
6977 if( activityunreliable )
6978 {
6980 newlb = (rhs - minresactivity)/val;
6981
6983 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6984 && (!force || !SCIPisGT(scip, newlb, lb)));
6985 }
6986
6987 if( !activityunreliable )
6988 {
6989 /* tighten lower bound */
6990 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6991 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6993 &infeasible, &tightened) );
6994 if( infeasible )
6995 {
6996 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6998
6999 /* analyze conflict */
7001
7002 *cutoff = TRUE;
7003 return SCIP_OKAY;
7004 }
7005 if( tightened )
7006 {
7007 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7009 (*nchgbds)++;
7010 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7011 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7012 }
7013 }
7014 }
7015 }
7016
7017 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
7018 {
7019 SCIP_Real newub;
7020
7021 newub = (lhs - maxresactivity)/val;
7022 if( !SCIPisInfinity(scip, newub) &&
7023 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
7024 {
7025 /* check maxresactivities for reliability */
7026 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
7027 {
7029 newub = (lhs - maxresactivity)/val;
7030
7033 && (!force || !SCIPisLT(scip, newub, ub))) )
7034 return SCIP_OKAY;
7035 }
7036
7037 /* tighten upper bound */
7038 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
7039 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
7041 &infeasible, &tightened) );
7042 if( infeasible )
7043 {
7044 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7046
7047 /* analyze conflict */
7049
7050 *cutoff = TRUE;
7051 return SCIP_OKAY;
7052 }
7053 if( tightened )
7054 {
7055 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7057 (*nchgbds)++;
7058 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7059 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7060 }
7061 }
7062 }
7063 }
7064
7065 return SCIP_OKAY;
7066}
7067
7068#define MAXTIGHTENROUNDS 10
7069
7070/** tightens bounds of variables in constraint due to activity bounds */
7071static
7073 SCIP* scip, /**< SCIP data structure */
7074 SCIP_CONS* cons, /**< linear constraint */
7075 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7076 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7077 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7078 int* nchgbds /**< pointer to count the total number of tightened bounds */
7079 )
7080{
7081 SCIP_CONSDATA* consdata;
7082 unsigned int tightenmode;
7083 int nvars;
7084 int nrounds;
7085 int lastchange;
7086 int oldnchgbds;
7087#ifndef SCIP_DEBUG
7088 int oldnchgbdstotal;
7089#endif
7090 int v;
7091 SCIP_Bool force;
7092 SCIP_Bool easycase;
7093
7094 assert(scip != NULL);
7095 assert(cons != NULL);
7096 assert(nchgbds != NULL);
7097 assert(cutoff != NULL);
7098
7099 *cutoff = FALSE;
7100
7101 /* we cannot tighten variables' bounds, if the constraint may be not complete */
7102 if( SCIPconsIsModifiable(cons) )
7103 return SCIP_OKAY;
7104
7105 /* if a constraint was created after presolve, then it may hold fixed variables
7106 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7107 * thus, ensure here again that variable fixings have been applied
7108 */
7109 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7110 if( *cutoff )
7111 return SCIP_OKAY;
7112
7113 /* check if constraint has any chances of tightening bounds */
7114 if( !canTightenBounds(cons) )
7115 return SCIP_OKAY;
7116
7117 consdata = SCIPconsGetData(cons);
7118 assert(consdata != NULL);
7119
7120 nvars = consdata->nvars;
7121 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7122
7123 /* we are at the root node or during presolving */
7124 if( SCIPgetDepth(scip) < 1 )
7125 tightenmode = 2;
7126 else
7127 tightenmode = 1;
7128
7129 /* stop if we already tightened the constraint and the tightening is not forced */
7130 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7131 return SCIP_OKAY;
7132
7133 /* ensure that the variables are properly sorted */
7134 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7135 {
7136 SCIP_CALL( consdataSort(scip, consdata) );
7137 assert(consdata->coefsorted);
7138 }
7139
7140 /* update maximal activity delta if necessary */
7141 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7143
7144 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7145 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7146 checkMaxActivityDelta(scip, consdata);
7147
7148 /* this may happen if all variables are fixed */
7149 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7150 return SCIP_OKAY;
7151
7152 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7153 {
7154 SCIP_Real slack;
7155 SCIP_Real surplus;
7156 SCIP_Real minactivity;
7157 SCIP_Real maxactivity;
7158 SCIP_Bool minisrelax;
7159 SCIP_Bool maxisrelax;
7160 SCIP_Bool isminsettoinfinity;
7161 SCIP_Bool ismaxsettoinfinity;
7162
7163 /* use maximal activity delta to skip propagation (cannot deduce anything) */
7164 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax,
7166 assert(!SCIPisInfinity(scip, minactivity));
7167 assert(!SCIPisInfinity(scip, -maxactivity));
7168
7169 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7170 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7171
7172 /* check if the constraint will propagate */
7173 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7174 return SCIP_OKAY;
7175 }
7176
7177 /* check if we can use fast implementation for easy and numerically well behaved cases */
7178 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7179
7180 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7181 lastchange = -1;
7182 oldnchgbds = 0;
7183
7184#ifndef SCIP_DEBUG
7185 oldnchgbdstotal = *nchgbds;
7186#endif
7187
7188 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7189 {
7190 /* ensure that the variables are properly sorted
7191 *
7192 * note: it might happen that integer variables become binary during bound tightening at the root node
7193 */
7194 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7195 {
7196 SCIP_CALL( consdataSort(scip, consdata) );
7197 assert(consdata->coefsorted);
7198 }
7199
7200 /* mark the constraint to have the variables' bounds tightened */
7201 consdata->boundstightened = (unsigned int)tightenmode;
7202
7203 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7204 * sorting enables skipping variables
7205 */
7206 v = 0;
7207 while( v < nvars && v != lastchange && !(*cutoff) )
7208 {
7209 oldnchgbds = *nchgbds;
7210
7211 if( easycase )
7212 {
7213 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7214 }
7215 else
7216 {
7217 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7218 }
7219
7220 /* if there was no progress, skip the rest of the binary variables */
7221 if( *nchgbds > oldnchgbds )
7222 {
7223 lastchange = v;
7224 ++v;
7225 }
7226 else if( consdata->coefsorted && v < consdata->nbinvars - 1
7227 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7228 v = consdata->nbinvars;
7229 else
7230 ++v;
7231 }
7232
7233#ifndef SCIP_DEBUG
7234 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7235 *nchgbds - oldnchgbdstotal, nrounds);
7237#endif
7238 }
7239
7240#ifndef NDEBUG
7241 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7242 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7243#endif
7244
7245 return SCIP_OKAY;
7246}
7247
7248/** checks linear constraint for feasibility of given solution or current solution */
7249static
7251 SCIP* scip, /**< SCIP data structure */
7252 SCIP_CONS* cons, /**< linear constraint */
7253 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7254 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7255 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7256 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7257 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7258 )
7259{
7260 SCIP_CONSDATA* consdata;
7261 SCIP_Real activity;
7262 SCIP_Real absviol;
7263 SCIP_Real relviol;
7264 SCIP_Real lhsviol;
7265 SCIP_Real rhsviol;
7266
7267 assert(scip != NULL);
7268 assert(cons != NULL);
7269 assert(violated != NULL);
7270
7271 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7273
7274 consdata = SCIPconsGetData(cons);
7275 assert(consdata != NULL);
7276
7277 *violated = FALSE;
7278
7279 if( consdata->row != NULL )
7280 {
7281 if( !checklprows && SCIProwIsInLP(consdata->row) )
7282 return SCIP_OKAY;
7283 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7284 activity = consdataComputePseudoActivity(scip, consdata);
7285 else
7286 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7287 }
7288 else
7289 activity = consdataGetActivity(scip, consdata, sol);
7290
7291 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7292 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7293 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7294 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7295
7296 /* calculate absolute and relative bound violations */
7297 lhsviol = consdata->lhs - activity;
7298 rhsviol = activity - consdata->rhs;
7299
7300 absviol = 0.0;
7301 relviol = 0.0;
7302 if( (lhsviol > 0) && (lhsviol > rhsviol) )
7303 {
7304 absviol = lhsviol;
7305 relviol = SCIPrelDiff(consdata->lhs, activity);
7306 }
7307 else if( rhsviol > 0 )
7308 {
7309 absviol = rhsviol;
7310 relviol = SCIPrelDiff(activity, consdata->rhs);
7311 }
7312
7313 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7314 * return infeasible for safety
7315 */
7316 if( activity == SCIP_INVALID ) /*lint !e777*/
7317 {
7318 assert(sol == NULL);
7319 *violated = TRUE;
7320
7321 /* set violation of invalid pseudo solutions */
7324
7325 /* reset constraint age since we are in enforcement */
7327 }
7328 /* check with relative tolerances (the default) */
7329 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7330 {
7331 /* the "normal" check: one of the two sides is violated */
7332 if( !checkrelmaxabs )
7333 {
7334 *violated = TRUE;
7335
7336 /* only reset constraint age if we are in enforcement */
7337 if( sol == NULL )
7338 {
7340 }
7341 }
7342 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7343 * small compared to the absolute values occurring in the activity
7344 */
7345 else
7346 {
7347 SCIP_Real maxabs;
7348 SCIP_Real coef;
7349 SCIP_Real absval;
7350 SCIP_Real solval;
7351 int v;
7352
7353 maxabs = 1.0;
7354
7355 /* compute maximum absolute value */
7356 for( v = 0; v < consdata->nvars; ++v )
7357 {
7358 if( consdata->vals != NULL )
7359 {
7360 coef = consdata->vals[v];
7361 }
7362 else
7363 coef = 1.0;
7364
7365 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7366 absval = REALABS( coef * solval );
7367 maxabs = MAX( maxabs, absval );
7368 }
7369
7370 /* regard left hand side, first */
7371 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7372 {
7373 /* check whether violation is random noise */
7374 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7375 {
7376 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7377 consdata->lhs - activity, maxabs);
7379
7380 /* only increase constraint age if we are in enforcement */
7381 if( sol == NULL )
7382 {
7383 SCIP_CALL( SCIPincConsAge(scip, cons) );
7384 }
7385 }
7386 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7387 else if( SCIPisZero(scip, consdata->lhs) )
7388 {
7389 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7390 {
7391 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7392 consdata->lhs - activity, maxabs);
7394
7395 /* only increase constraint age if we are in enforcement */
7396 if( sol == NULL )
7397 {
7398 SCIP_CALL( SCIPincConsAge(scip, cons) );
7399 }
7400 }
7401 else
7402 {
7403 *violated = TRUE;
7404
7405 /* only reset constraint age if we are in enforcement */
7406 if( sol == NULL )
7407 {
7409 }
7410 }
7411 }
7412 else
7413 {
7414 *violated = TRUE;
7415
7416 /* only reset constraint age if we are in enforcement */
7417 if( sol == NULL )
7418 {
7420 }
7421 }
7422 }
7423
7424 /* now regard right hand side */
7425 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7426 {
7427 /* check whether violation is random noise */
7428 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7429 {
7430 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7431 activity - consdata->rhs, maxabs);
7433
7434 /* only increase constraint age if we are in enforcement */
7435 if( sol == NULL )
7436 {
7437 SCIP_CALL( SCIPincConsAge(scip, cons) );
7438 }
7439 }
7440 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7441 else if( SCIPisZero(scip, consdata->rhs) )
7442 {
7443 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7444 {
7445 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7446 activity - consdata->rhs, maxabs);
7448
7449 /* only increase constraint age if we are in enforcement */
7450 if( sol == NULL )
7451 {
7452 SCIP_CALL( SCIPincConsAge(scip, cons) );
7453 }
7454 }
7455 else
7456 {
7457 *violated = TRUE;
7458
7459 /* only reset constraint age if we are in enforcement */
7460 if( sol == NULL )
7461 {
7463 }
7464 }
7465 }
7466 else
7467 {
7468 *violated = TRUE;
7469
7470 /* only reset constraint age if we are in enforcement */
7471 if( sol == NULL )
7472 {
7474 }
7475 }
7476 }
7477 }
7478 }
7479 /* check with absolute tolerances */
7480 else if( consdata->checkabsolute &&
7481 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7482 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7483 {
7484 *violated = TRUE;
7485
7486 /* only reset constraint age if we are in enforcement */
7487 if( sol == NULL )
7488 {
7490 }
7491 }
7492 else
7493 {
7494 /* only increase constraint age if we are in enforcement */
7495 if( sol == NULL )
7496 {
7497 SCIP_CALL( SCIPincConsAge(scip, cons) );
7498 }
7499 }
7500
7501 /* update absolute and relative violation of the solution */
7502 if( sol != NULL )
7504
7505 return SCIP_OKAY;
7506}
7507
7508/** creates an LP row in a linear constraint data */
7509static
7511 SCIP* scip, /**< SCIP data structure */
7512 SCIP_CONS* cons /**< linear constraint */
7513 )
7514{
7515 SCIP_CONSDATA* consdata;
7516
7517 assert(scip != NULL);
7518 assert(cons != NULL);
7519
7520 consdata = SCIPconsGetData(cons);
7521 assert(consdata != NULL);
7522 assert(consdata->row == NULL);
7523
7524 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7526
7527 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7528
7529 return SCIP_OKAY;
7530}
7531
7532/** adds linear constraint as cut to the LP */
7533static
7535 SCIP* scip, /**< SCIP data structure */
7536 SCIP_CONS* cons, /**< linear constraint */
7537 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7538 )
7539{
7540 SCIP_CONSDATA* consdata;
7541
7542 assert(scip != NULL);
7543 assert(cons != NULL);
7544
7545 consdata = SCIPconsGetData(cons);
7546 assert(consdata != NULL);
7547
7548 if( consdata->row == NULL )
7549 {
7550 if( !SCIPconsIsModifiable(cons) )
7551 {
7552 /* 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
7553 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7554 */
7555 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7556 if( *cutoff )
7557 return SCIP_OKAY;
7558 }
7559
7560 /* convert consdata object into LP row */
7561 SCIP_CALL( createRow(scip, cons) );
7562 }
7563 assert(consdata->row != NULL);
7564
7565 if( consdata->nvars == 0 )
7566 {
7567 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7568 }
7569
7570 /* insert LP row as cut */
7571 if( !SCIProwIsInLP(consdata->row) )
7572 {
7573 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7574 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7575 /* if presolving is turned off, the row might be trivial */
7576 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7577 {
7578 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7579 }
7580#ifndef NDEBUG
7581 else
7582 {
7583 int pr;
7584 int cr;
7585 SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7586 SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7587 assert( pr == 0 || cr == 0 );
7588 }
7589#endif
7590 }
7591
7592 return SCIP_OKAY;
7593}
7594
7595/** adds linear constraint as row to the NLP, if not added yet */
7596static
7598 SCIP* scip, /**< SCIP data structure */
7599 SCIP_CONS* cons /**< linear constraint */
7600 )
7601{
7602 SCIP_CONSDATA* consdata;
7603
7605
7606 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7607 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7608 return SCIP_OKAY;
7609
7610 consdata = SCIPconsGetData(cons);
7611 assert(consdata != NULL);
7612
7613 if( consdata->nlrow == NULL )
7614 {
7615 assert(consdata->lhs <= consdata->rhs);
7616
7617 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7618 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7619
7620 assert(consdata->nlrow != NULL);
7621 }
7622
7623 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7624 {
7625 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7626 }
7627
7628 return SCIP_OKAY;
7629}
7630
7631/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7632static
7634 SCIP* scip, /**< SCIP data structure */
7635 SCIP_CONS* cons, /**< linear constraint */
7636 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7637 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7638 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7639 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7640 * the ones with non-zero dual value? */
7641 int* ncuts, /**< pointer to add up the number of found cuts */
7642 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7643 )
7644{
7645 SCIP_CONSDATA* consdata;
7646 SCIP_Bool violated;
7647 int oldncuts;
7648
7649 assert(scip != NULL);
7650 assert(conshdlrdata != NULL);
7651 assert(cons != NULL);
7652 assert(cutoff != NULL);
7653
7654 consdata = SCIPconsGetData(cons);
7655 assert(ncuts != NULL);
7656 assert(consdata != NULL);
7657
7658 oldncuts = *ncuts;
7659 *cutoff = FALSE;
7660
7661 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7662
7663 if( violated )
7664 {
7665 /* insert LP row as cut */
7667 (*ncuts)++;
7668 }
7669 else if( !SCIPconsIsModifiable(cons) && separatecards )
7670 {
7671 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7672 if( !separateall && sol == NULL )
7673 {
7674 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7675 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7676 {
7677 SCIP_Real dualsol;
7678
7679 dualsol = SCIProwGetDualsol(consdata->row);
7680 if( SCIPisFeasNegative(scip, dualsol) )
7681 {
7682 if( !SCIPisInfinity(scip, consdata->rhs) )
7683 {
7684 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7685 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7686 }
7687 }
7688 else if( SCIPisFeasPositive(scip, dualsol) )
7689 {
7690 if( !SCIPisInfinity(scip, -consdata->lhs) )
7691 {
7692 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7693 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7694 }
7695 }
7696 }
7697 }
7698 else
7699 {
7700 if( !SCIPisInfinity(scip, consdata->rhs) )
7701 {
7702 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7703 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7704 }
7705 if( !SCIPisInfinity(scip, -consdata->lhs) )
7706 {
7707 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7708 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7709 }
7710 }
7711 }
7712
7713 if( *ncuts > oldncuts )
7714 {
7716 }
7717
7718 return SCIP_OKAY;
7719}
7720
7721/** propagation method for linear constraints */
7722static
7724 SCIP* scip, /**< SCIP data structure */
7725 SCIP_CONS* cons, /**< linear constraint */
7726 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7727 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7728 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7729 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7730 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7731 int* nchgbds /**< pointer to count the total number of tightened bounds */
7732 )
7733{
7734 SCIP_CONSDATA* consdata;
7735 SCIP_Real minactivity;
7736 SCIP_Real maxactivity;
7737 SCIP_Bool minactisrelax;
7738 SCIP_Bool maxactisrelax;
7739 SCIP_Bool isminsettoinfinity;
7740 SCIP_Bool ismaxsettoinfinity;
7741
7742 assert(scip != NULL);
7743 assert(cons != NULL);
7744 assert(cutoff != NULL);
7745 assert(nchgbds != NULL);
7746
7747 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7748
7749 consdata = SCIPconsGetData(cons);
7750 assert(consdata != NULL);
7751
7752 if( consdata->eventdata == NULL )
7753 {
7754 SCIP_CONSHDLR* conshdlr;
7755 SCIP_CONSHDLRDATA* conshdlrdata;
7756
7757 conshdlr = SCIPconsGetHdlr(cons);
7758 assert(conshdlr != NULL);
7759
7760 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7761 assert(conshdlrdata != NULL);
7762
7763 /* catch bound change events of variables */
7764 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7765 assert(consdata->eventdata != NULL);
7766 }
7767
7768 *cutoff = FALSE;
7769
7770 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7771 if( !SCIPconsIsModifiable(cons) )
7772 {
7773 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7775 {
7776 SCIP_CALL( SCIPincConsAge(scip, cons) );
7777 }
7778
7779 /* tighten the variable's bounds */
7780 if( tightenbounds )
7781 {
7782 int oldnchgbds;
7783
7784 oldnchgbds = *nchgbds;
7785
7786 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7787
7788 if( *nchgbds > oldnchgbds )
7789 {
7791 }
7792 }
7793
7794 /* propagate ranged rows */
7795 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7796 {
7797 int nfixedvars;
7798 int naddconss;
7799 SCIPdebug( int oldnchgbds = *nchgbds; )
7800
7801 nfixedvars = 0;
7802 naddconss = 0;
7803
7804 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7805
7806 if( *cutoff )
7807 {
7808 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7809 }
7810 else
7811 {
7812 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7813 }
7814
7815 if( nfixedvars > 0 )
7816 *nchgbds += 2*nfixedvars;
7817 } /*lint !e438*/
7818
7819 /* check constraint for infeasibility and redundancy */
7820 if( !(*cutoff) )
7821 {
7822 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
7824
7825 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7826 {
7827 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7828 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7829
7830 /* analyze conflict */
7832
7834 *cutoff = TRUE;
7835 }
7836 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7837 {
7838 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7839 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7840
7841 /* analyze conflict */
7843
7845 *cutoff = TRUE;
7846 }
7847 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7848 {
7849 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7850 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7851
7852 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7853 if( consdata->nvars > 0 )
7855 else
7856 SCIP_CALL( SCIPdelCons(scip, cons) );
7857 }
7858 }
7859 }
7860
7861 return SCIP_OKAY;
7862}
7863
7864
7865/*
7866 * Presolving methods
7867 */
7868
7869/** converts all variables with fixed domain into FIXED variables */
7870static
7872 SCIP* scip, /**< SCIP data structure */
7873 SCIP_CONS* cons, /**< linear constraint */
7874 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7875 int* nfixedvars /**< pointer to count the total number of fixed variables */
7876 )
7877{
7878 SCIP_CONSDATA* consdata;
7879 SCIP_VAR* var;
7880 SCIP_VARSTATUS varstatus;
7881 SCIP_Real lb;
7882 SCIP_Real ub;
7883 SCIP_Bool fixed;
7884 SCIP_Bool infeasible;
7885 int v;
7886
7887 assert(scip != NULL);
7888 assert(cons != NULL);
7889 assert(cutoff != NULL);
7890 assert(nfixedvars != NULL);
7891
7892 consdata = SCIPconsGetData(cons);
7893 assert(consdata != NULL);
7894
7895 for( v = 0; v < consdata->nvars; ++v )
7896 {
7897 assert(consdata->vars != NULL);
7898 var = consdata->vars[v];
7899 varstatus = SCIPvarGetStatus(var);
7900
7901 if( varstatus != SCIP_VARSTATUS_FIXED )
7902 {
7903 lb = SCIPvarGetLbGlobal(var);
7904 ub = SCIPvarGetUbGlobal(var);
7905 if( SCIPisEQ(scip, lb, ub) )
7906 {
7907 SCIP_Real fixval;
7908
7910 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7911 SCIPvarGetName(var), lb, ub, fixval);
7912 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7913 if( infeasible )
7914 {
7915 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7916 *cutoff = TRUE;
7917 return SCIP_OKAY;
7918 }
7919 if( fixed )
7920 (*nfixedvars)++;
7921 }
7922 }
7923 }
7924
7925 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7926
7927 if( infeasible )
7928 {
7929 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7930 *cutoff = TRUE;
7931 return SCIP_OKAY;
7932 }
7933
7934 assert(consdata->removedfixings);
7935
7936 return SCIP_OKAY;
7937}
7938
7939#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7940
7941/** extracts cliques of the constraint and adds them to SCIP
7942 *
7943 * The following clique extraction mechanism are implemeneted
7944 *
7945 * 1. collect binary variables and sort them in non increasing order, then
7946 *
7947 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7948 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7949 * condition
7950 *
7951 * minactivity + vals[i] + vals[i+1] > rhs
7952 *
7953 * and also add the binary to binary implication also for non-successive variables for which the same argument
7954 * holds
7955 *
7956 * minactivity + vals[i] + vals[j] > rhs
7957 *
7958 * 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
7959 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7960 *
7961 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7962 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7963 * condition
7964 *
7965 * maxactivity + vals[i] + vals[i-1] < lhs
7966 *
7967 * and also add the binary to binary implication also for non-successive variables for which the same argument
7968 * holds
7969 *
7970 * maxactivity + vals[i] + vals[j] < lhs
7971 *
7972 * e.g. you could multiply the above example by -1
7973 *
7974 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7975 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7976 * condition
7977 *
7978 * minactivity - vals[i] - vals[i-1] > rhs
7979 *
7980 * and also add the binary to binary implication also for non-successive variables for which the
7981 * same argument holds
7982 *
7983 * minactivity - vals[i] - vals[j] > rhs
7984 *
7985 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7986 * implication x1 = 0 => x3 = 1
7987 *
7988 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7989 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7990 * condition
7991 *
7992 * maxactivity - vals[i] - vals[i+1] < lhs
7993 *
7994 * and also add the binary to binary implication also for non-successive variables for which the same argument
7995 * holds
7996 *
7997 * maxactivity - vals[i] - vals[j] < lhs
7998 *
7999 * e.g. you could multiply the above example by -1
8000 *
8001 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
8002 * as clique, (this part is done at the end of the method)
8003 *
8004 */
8005static
8007 SCIP* scip, /**< SCIP data structure */
8008 SCIP_CONS* cons, /**< linear constraint */
8009 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
8010 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
8011 int* nfixedvars, /**< pointer to count number of fixed variables */
8012 int* nchgbds, /**< pointer to count the total number of tightened bounds */
8013 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
8014 )
8015{
8016 SCIP_VAR** vars;
8017 SCIP_Real* vals;
8018 SCIP_CONSDATA* consdata;
8019 SCIP_Bool lhsclique;
8020 SCIP_Bool rhsclique;
8021 SCIP_Bool finitelhs;
8022 SCIP_Bool finiterhs;
8023 SCIP_Bool finiteminact;
8024 SCIP_Bool finitemaxact;
8025 SCIP_Bool finitenegminact;
8026 SCIP_Bool finitenegmaxact;
8027 SCIP_Bool finiteposminact;
8028 SCIP_Bool finiteposmaxact;
8029 SCIP_Bool infeasible;
8030 SCIP_Bool stopped;
8032 int v;
8033 int i;
8034 int nposcoefs;
8035 int nnegcoefs;
8036 int nvars;
8037
8038 assert(scip != NULL);
8039 assert(cons != NULL);
8040 assert(nfixedvars != NULL);
8041 assert(nchgbds != NULL);
8042 assert(cutoff != NULL);
8043 assert(!SCIPconsIsDeleted(cons));
8044
8045 consdata = SCIPconsGetData(cons);
8046 assert(consdata != NULL);
8047
8048 if( consdata->nvars < 2 )
8049 return SCIP_OKAY;
8050
8051 /* add implications if possible
8052 *
8053 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
8054 * maximal absolute contribution and also only if this variable would force all other variables to their bound
8055 * corresponding to the global minimal activity of the constraint
8056 */
8057 if( !consdata->implsadded )
8058 {
8059 /* sort variables by variable type */
8060 SCIP_CALL( consdataSort(scip, consdata) );
8061
8062 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
8063 * up front, might change sorting correspondingly
8064 */
8065 /* fast abort if no binaries seem to exist
8066 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
8067 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
8068 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
8069 * which is the requirement for consdataSort() to actually resort the variables
8070 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
8071 */
8072 if( !SCIPvarIsBinary(consdata->vars[0]) )
8073 return SCIP_OKAY;
8074
8075 nvars = consdata->nvars;
8076 vars = consdata->vars;
8077 vals = consdata->vals;
8078
8079 /* recompute activities if needed */
8080 if( !consdata->validactivities )
8081 consdataCalcActivities(scip, consdata);
8082 assert(consdata->validactivities);
8083
8084 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8085 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8086 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8087 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8088 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8089 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8092
8094 {
8095 SCIP_Real maxabscontrib = -1.0;
8096 SCIP_Bool posval = FALSE;
8097 SCIP_Bool allbinary = TRUE;
8098 int oldnchgbds = *nchgbds;
8099 int nbdchgs = 0;
8100 int nimpls = 0;
8101 int position = -1;
8102
8103 /* we need a valid minimal/maximal activity to add cliques */
8104 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8105 {
8107 assert(consdata->validglbminact);
8108 }
8109
8110 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8111 {
8113 assert(consdata->validglbmaxact);
8114 }
8115 assert(consdata->validglbminact || consdata->validglbmaxact);
8116
8117 /* @todo extend this to local/constraint probing */
8118
8119 /* determine maximal contribution to the activity */
8120 for( v = nvars - 1; v >= 0; --v )
8121 {
8122 if( SCIPvarIsBinary(vars[v]) )
8123 {
8124 if( vals[v] > 0 )
8125 {
8126 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8127
8128 if( value > maxabscontrib )
8129 {
8130 maxabscontrib = value;
8131 position = v;
8132 posval = TRUE;
8133 }
8134 }
8135 else
8136 {
8137 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8138
8139 value = REALABS(value);
8140
8141 if( value > maxabscontrib )
8142 {
8143 maxabscontrib = value;
8144 position = v;
8145 posval = FALSE;
8146 }
8147 }
8148 }
8149 else
8150 allbinary = FALSE;
8151 }
8152 assert(0 <= position && position < nvars);
8153
8154 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8155 {
8156 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8157 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8158 * implications
8159 */
8160 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8161 {
8162 for( v = nvars - 1; v >= 0; --v )
8163 {
8164 /* binary to binary implications will be collected when extrating cliques */
8165 if( !SCIPvarIsBinary(vars[v]) )
8166 {
8167 if( v != position )
8168 {
8169 if( vals[v] > 0 )
8170 {
8171 /* add implications */
8172 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8173 ++nimpls;
8174 *nchgbds += nbdchgs;
8175 }
8176 else
8177 {
8178 /* add implications */
8179 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8180 ++nimpls;
8181 *nchgbds += nbdchgs;
8182 }
8183
8184 if( infeasible )
8185 {
8186 *cutoff = TRUE;
8187 break;
8188 }
8189 }
8190 }
8191 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8192 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8193 break;
8194 }
8195 }
8196
8197 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8198 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8199 * implications
8200 */
8201 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8202 {
8203 for( v = nvars - 1; v >= 0; --v )
8204 {
8205 /* binary to binary implications will be collected when extrating cliques */
8206 if( !SCIPvarIsBinary(vars[v]) )
8207 {
8208 if( v != position )
8209 {
8210 if( vals[v] > 0 )
8211 {
8212 /* add implications */
8213 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8214 ++nimpls;
8215 *nchgbds += nbdchgs;
8216 }
8217 else
8218 {
8219 /* add implications */
8220 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8221 ++nimpls;
8222 *nchgbds += nbdchgs;
8223 }
8224
8225 if( infeasible )
8226 {
8227 *cutoff = TRUE;
8228 break;
8229 }
8230 }
8231 }
8232 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8233 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8234 break;
8235 }
8236 }
8237
8238 /* did we find some implications */
8239 if( nimpls > 0 )
8240 {
8241 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8242
8243 if( *cutoff )
8244 return SCIP_OKAY;
8245
8246 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8247 if( *nchgbds - oldnchgbds > 0 )
8248 {
8249 /* check for fixed variables */
8250 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8251 if( *cutoff )
8252 return SCIP_OKAY;
8253
8254 /* tighten variable's bounds */
8255 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8256 if( *cutoff )
8257 return SCIP_OKAY;
8258
8259 /* check for fixed variables */
8260 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8261 if( *cutoff )
8262 return SCIP_OKAY;
8263 }
8264 }
8265 }
8266 }
8267
8268 consdata->implsadded = TRUE;
8269 }
8270
8271 /* check if we already added the cliques of this constraint */
8272 if( consdata->cliquesadded )
8273 return SCIP_OKAY;
8274
8275 consdata->cliquesadded = TRUE;
8277 stopped = FALSE;
8278
8279 /* sort variables by variable type */
8280 SCIP_CALL( consdataSort(scip, consdata) );
8281
8282 nvars = consdata->nvars;
8283 vars = consdata->vars;
8284 vals = consdata->vals;
8285
8286 /**@todo extract more cliques, implications and variable bounds from linear constraints */
8287
8288 /* recompute activities if needed */
8289 if( !consdata->validactivities )
8290 consdataCalcActivities(scip, consdata);
8291 assert(consdata->validactivities);
8292
8293 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8294 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8295 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8296 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8297 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8298 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8301
8302 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8303 * information
8304 */
8306 {
8307 SCIP_VAR** binvars;
8308 SCIP_Real* binvarvals;
8309 int nposbinvars = 0;
8310 int nnegbinvars = 0;
8311 int allonebinary = 0;
8312
8315
8316 /* collect binary variables */
8317 for( i = 0; i < nvars; ++i )
8318 {
8319 if( SCIPvarIsBinary(vars[i]) )
8320 {
8321 assert(!SCIPisZero(scip, vals[i]));
8322
8323 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8324 ++allonebinary;
8325
8326 binvars[nposbinvars + nnegbinvars] = vars[i];
8328
8329 if( SCIPisPositive(scip, vals[i]) )
8330 ++nposbinvars;
8331 else
8332 ++nnegbinvars;
8333
8335 }
8336 /* stop searching for binary variables, because the constraint data is sorted */
8338 break;
8339 }
8341
8342 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8343 * cliques
8344 */
8345 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8346 {
8347 SCIP_Real threshold;
8348 int oldnchgbds = *nchgbds;
8349 int nbdchgs;
8350 int jstart;
8351 int j;
8352
8353 /* we need a valid minimal/maximal activity to add cliques */
8354 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8355 {
8357 assert(consdata->validglbminact);
8358 }
8359
8360 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8361 {
8363 assert(consdata->validglbmaxact);
8364 }
8365 assert(consdata->validglbminact || consdata->validglbmaxact);
8366
8367 /* sort coefficients non-increasing to be faster in the clique search */
8369
8370 /* case a) */
8371 if( finiterhs && finitenegminact && nposbinvars >= 2 )
8372 {
8373 /* compute value that needs to be exceeded */
8374 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8375
8376 j = 1;
8377#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8378 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8380#endif
8381 /* check if at least two variables are in a clique */
8383 {
8384 ++j;
8385 /* check for extending the clique */
8386 while( j < nposbinvars )
8387 {
8389 break;
8390 ++j;
8391 }
8392 assert(j >= 2);
8393
8394 /* add clique with at least two variables */
8395 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8396
8397 if( infeasible )
8398 *cutoff = TRUE;
8399
8400 *nchgbds += nbdchgs;
8401
8404 stopped = TRUE;
8405
8406 /* exchange the last variable in the clique if possible and add all new ones */
8407 if( !stopped && !(*cutoff) && j < nposbinvars )
8408 {
8409 SCIP_VAR** clqvars;
8410 int lastfit = j - 2;
8411 assert(lastfit >= 0);
8412
8413 /* copy all 'main'-clique variables */
8415
8416 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8417 while( lastfit >= 0 && j < nposbinvars )
8418 {
8419 /* check if two variables are in a clique */
8421 {
8422 clqvars[lastfit + 1] = binvars[j];
8423
8424 /* add clique with at least two variables */
8425 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8426
8427 if( infeasible )
8428 {
8429 *cutoff = TRUE;
8430 break;
8431 }
8432
8433 *nchgbds += nbdchgs;
8434
8437 {
8438 stopped = TRUE;
8439 break;
8440 }
8441
8442 ++j;
8443 }
8444 else
8445 --lastfit;
8446 }
8447
8449 }
8450 }
8451 }
8452
8453 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8454 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8455 {
8456 /* check for fixed variables */
8457 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8458
8459 if( !*cutoff )
8460 {
8461 /* tighten variable's bounds */
8462 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8463
8464 if( !*cutoff )
8465 {
8466 /* check for fixed variables */
8467 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8468
8469 if( !*cutoff )
8470 {
8471 /* sort variables by variable type */
8472 SCIP_CALL( consdataSort(scip, consdata) );
8473
8474 /* recompute activities if needed */
8475 if( !consdata->validactivities )
8476 consdataCalcActivities(scip, consdata);
8477 assert(consdata->validactivities);
8478
8479 nvars = consdata->nvars;
8480 vars = consdata->vars;
8481 vals = consdata->vals;
8482 nposbinvars = 0;
8483 nnegbinvars = 0;
8484 allonebinary = 0;
8485
8486 /* update binary variables */
8487 for( i = 0; i < nvars; ++i )
8488 {
8489 if( SCIPvarIsBinary(vars[i]) )
8490 {
8491 assert(!SCIPisZero(scip, vals[i]));
8492
8493 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8494 ++allonebinary;
8495
8496 binvars[nposbinvars + nnegbinvars] = vars[i];
8498
8499 if( SCIPisPositive(scip, vals[i]) )
8500 ++nposbinvars;
8501 else
8502 ++nnegbinvars;
8503
8505 }
8506 /* stop searching for binary variables, because the constraint data is sorted */
8508 break;
8509 }
8511 }
8512 }
8513 }
8514
8515 oldnchgbds = *nchgbds;
8516 }
8517
8518 /* case b) */
8519 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8520 {
8521 /* compute value that needs to be deceeded */
8522 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8523
8524 i = nposbinvars + nnegbinvars - 1;
8525 j = i - 1;
8526#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8527 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8529#endif
8530 /* check if two variables are in a clique */
8532 {
8533 --j;
8534 /* check for extending the clique */
8535 while( j >= nposbinvars )
8536 {
8538 break;
8539 --j;
8540 }
8541 jstart = j;
8542
8543 assert(i - j >= 2);
8544 /* add clique with at least two variables */
8545 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8546
8547 if( infeasible )
8548 *cutoff = TRUE;
8549
8550 *nchgbds += nbdchgs;
8551
8552 cliquenonzerosadded += (i - j);
8554 stopped = TRUE;
8555
8556 /* exchange the last variable in the clique if possible and add all new ones */
8557 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8558 {
8559 SCIP_VAR** clqvars;
8560 int lastfit = jstart + 1;
8561 assert(lastfit < i);
8562
8563 /* copy all 'main'-clique variables */
8565 ++lastfit;
8566
8567 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8569 {
8570 /* check if two variables are in a clique */
8572 {
8573 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8574 clqvars[lastfit - jstart - 2] = binvars[j];
8575
8576 assert(i - lastfit + 2 >= 2);
8577 /* add clique with at least two variables */
8578 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8579
8580 if( infeasible )
8581 {
8582 *cutoff = TRUE;
8583 break;
8584 }
8585
8586 *nchgbds += nbdchgs;
8587
8588 cliquenonzerosadded += (i - lastfit + 2);
8590 {
8591 stopped = TRUE;
8592 break;
8593 }
8594
8595 --j;
8596 }
8597 else
8598 ++lastfit;
8599 }
8600
8602 }
8603 }
8604 }
8605
8606 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8607 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8608 {
8609 /* check for fixed variables */
8610 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8611
8612 if( !*cutoff )
8613 {
8614 /* tighten variable's bounds */
8615 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8616
8617 if( !*cutoff )
8618 {
8619 /* check for fixed variables */
8620 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8621
8622 if( !*cutoff )
8623 {
8624 /* sort variables by variable type */
8625 SCIP_CALL( consdataSort(scip, consdata) );
8626
8627 /* recompute activities if needed */
8628 if( !consdata->validactivities )
8629 consdataCalcActivities(scip, consdata);
8630 assert(consdata->validactivities);
8631
8632 nvars = consdata->nvars;
8633 vars = consdata->vars;
8634 vals = consdata->vals;
8635 nposbinvars = 0;
8636 nnegbinvars = 0;
8637 allonebinary = 0;
8638
8639 /* update binary variables */
8640 for( i = 0; i < nvars; ++i )
8641 {
8642 if( SCIPvarIsBinary(vars[i]) )
8643 {
8644 assert(!SCIPisZero(scip, vals[i]));
8645
8646 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8647 ++allonebinary;
8648
8649 binvars[nposbinvars + nnegbinvars] = vars[i];
8651
8652 if( SCIPisPositive(scip, vals[i]) )
8653 ++nposbinvars;
8654 else
8655 ++nnegbinvars;
8656
8658 }
8659 /* stop searching for binary variables, because the constraint data is sorted */
8661 break;
8662 }
8664 }
8665 }
8666 }
8667
8668 oldnchgbds = *nchgbds;
8669 }
8670
8671 /* case c) */
8672 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8673 {
8674 SCIP_Bool* values;
8675
8676 /* initialize clique values array for adding a negated clique */
8679
8680 /* compute value that needs to be exceeded */
8681 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8682
8683 i = nposbinvars + nnegbinvars - 1;
8684 j = i - 1;
8685
8686#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8687 /* check if the variable should not have already been fixed to one */
8689#endif
8690
8692 {
8693 --j;
8694 /* check for extending the clique */
8695 while( j >= nposbinvars )
8696 {
8698 break;
8699 --j;
8700 }
8701 jstart = j;
8702
8703 assert(i - j >= 2);
8704 /* add negated clique with at least two variables */
8705 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8706
8707 if( infeasible )
8708 *cutoff = TRUE;
8709
8710 *nchgbds += nbdchgs;
8711
8712 cliquenonzerosadded += (i - j);
8714 stopped = TRUE;
8715
8716 /* exchange the last variable in the clique if possible and add all new ones */
8717 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8718 {
8719 SCIP_VAR** clqvars;
8720 int lastfit = j + 1;
8721 assert(lastfit < i);
8722
8723 /* copy all 'main'-clique variables */
8725 ++lastfit;
8726
8727 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8729 {
8730 /* check if two variables are in a negated clique */
8732 {
8733 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8734 clqvars[lastfit - jstart - 2] = binvars[j];
8735
8736 assert(i - lastfit + 2 >= 2);
8737 /* add clique with at least two variables */
8738 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8739
8740 if( infeasible )
8741 {
8742 *cutoff = TRUE;
8743 break;
8744 }
8745
8746 *nchgbds += nbdchgs;
8747
8748 cliquenonzerosadded += (i - lastfit + 2);
8750 {
8751 stopped = TRUE;
8752 break;
8753 }
8754
8755 --j;
8756 }
8757 else
8758 ++lastfit;
8759 }
8760
8762 }
8763 }
8764
8765 SCIPfreeBufferArray(scip, &values);
8766 }
8767
8768 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8769 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8770 {
8771 /* check for fixed variables */
8772 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8773
8774 if( !*cutoff )
8775 {
8776 /* tighten variable's bounds */
8777 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8778
8779 if( !*cutoff )
8780 {
8781 /* check for fixed variables */
8782 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8783
8784 if( !*cutoff )
8785 {
8786 /* sort variables by variable type */
8787 SCIP_CALL( consdataSort(scip, consdata) );
8788
8789 /* recompute activities if needed */
8790 if( !consdata->validactivities )
8791 consdataCalcActivities(scip, consdata);
8792 assert(consdata->validactivities);
8793
8794 nvars = consdata->nvars;
8795 vars = consdata->vars;
8796 vals = consdata->vals;
8797 nposbinvars = 0;
8798 nnegbinvars = 0;
8799 allonebinary = 0;
8800
8801 /* update binary variables */
8802 for( i = 0; i < nvars; ++i )
8803 {
8804 if( SCIPvarIsBinary(vars[i]) )
8805 {
8806 assert(!SCIPisZero(scip, vals[i]));
8807
8808 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8809 ++allonebinary;
8810
8811 binvars[nposbinvars + nnegbinvars] = vars[i];
8813
8814 if( SCIPisPositive(scip, vals[i]) )
8815 ++nposbinvars;
8816 else
8817 ++nnegbinvars;
8818
8820 }
8821 /* stop searching for binary variables, because the constraint data is sorted */
8823 break;
8824 }
8826 }
8827 }
8828 }
8829 }
8830
8831 /* case d) */
8832 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8833 {
8834 SCIP_Bool* values;
8835
8836 /* initialize clique values array for adding a negated clique */
8839
8840 /* compute value that needs to be exceeded */
8841 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8842
8843 j = 1;
8844
8845#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8846 /* check if the variable should not have already been fixed to one */
8848#endif
8849
8851 {
8852 ++j;
8853 /* check for extending the clique */
8854 while( j < nposbinvars )
8855 {
8857 break;
8858 ++j;
8859 }
8860 assert(j >= 2);
8861
8862 /* add negated clique with at least two variables */
8863 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8864
8865 if( infeasible )
8866 *cutoff = TRUE;
8867
8868 *nchgbds += nbdchgs;
8869
8872 stopped = TRUE;
8873
8874 /* exchange the last variable in the clique if possible and add all new ones */
8875 if( !stopped && !(*cutoff) && j < nposbinvars )
8876 {
8877 SCIP_VAR** clqvars;
8878 int lastfit = j - 2;
8879 assert(lastfit >= 0);
8880
8881 /* copy all 'main'-clique variables */
8883
8884 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8885 while( lastfit >= 0 && j < nposbinvars )
8886 {
8887 /* check if two variables are in a negated clique */
8889 {
8890 clqvars[lastfit + 1] = binvars[j];
8891
8892 /* add clique with at least two variables */
8893 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8894
8895 if( infeasible )
8896 {
8897 *cutoff = TRUE;
8898 break;
8899 }
8900
8901 *nchgbds += nbdchgs;
8902
8905 break;
8906
8907 ++j;
8908 }
8909 else
8910 --lastfit;
8911 }
8912
8914 }
8915 }
8916
8917 SCIPfreeBufferArray(scip, &values);
8918 }
8919 }
8920
8922 SCIPfreeBufferArray(scip, &binvars);
8923
8924 if( *cutoff )
8925 return SCIP_OKAY;
8926 }
8927
8928 /* 2. we only check if the constraint is a set packing / partitioning constraint */
8929
8930 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8931 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8932 */
8933 nposcoefs = 0;
8934 nnegcoefs = 0;
8935 for( i = 0; i < nvars; ++i )
8936 {
8937 if( !SCIPvarIsBinary(vars[i]) )
8938 return SCIP_OKAY;
8939 else if( SCIPisEQ(scip, vals[i], +1.0) )
8940 nposcoefs++;
8941 else if( SCIPisEQ(scip, vals[i], -1.0) )
8942 nnegcoefs++;
8943 else
8944 return SCIP_OKAY;
8945 }
8946
8947 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8948 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8949
8950 if( lhsclique || rhsclique )
8951 {
8952 SCIP_Bool* values;
8953 int nbdchgs;
8954
8955 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8958
8959 for( i = 0; i < nvars; ++i )
8960 values[i] = (rhsclique == (vals[i] > 0.0));
8961
8962 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8963
8964 if( infeasible )
8965 *cutoff = TRUE;
8966
8967 *nchgbds += nbdchgs;
8968 SCIPfreeBufferArray(scip, &values);
8969 }
8970
8971 return SCIP_OKAY;
8972}
8973
8974/** tightens left and right hand side of constraint due to integrality */
8975static
8977 SCIP* scip, /**< SCIP data structure */
8978 SCIP_CONS* cons, /**< linear constraint */
8979 int* nchgsides, /**< pointer to count number of side changes */
8980 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8981 )
8982{
8983 SCIP_CONSDATA* consdata;
8984 SCIP_Real newlhs;
8985 SCIP_Real newrhs;
8986 SCIP_Bool chglhs;
8987 SCIP_Bool chgrhs;
8988 SCIP_Bool integral;
8989 int i;
8990
8991 assert(scip != NULL);
8992 assert(cons != NULL);
8993 assert(nchgsides != NULL);
8994 assert(infeasible != NULL);
8995
8996 consdata = SCIPconsGetData(cons);
8997 assert(consdata != NULL);
8998
8999 *infeasible = FALSE;
9000
9001 chglhs = FALSE;
9002 chgrhs = FALSE;
9005
9006 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
9007 {
9008 integral = TRUE;
9009 for( i = 0; i < consdata->nvars && integral; ++i )
9010 {
9011 integral = SCIPisIntegral(scip, consdata->vals[i])
9012 && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
9013 }
9014 if( integral )
9015 {
9016 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
9017 {
9018 newlhs = SCIPfeasCeil(scip, consdata->lhs);
9019 chglhs = TRUE;
9020 }
9021 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
9022 {
9023 newrhs = SCIPfeasFloor(scip, consdata->rhs);
9024 chgrhs = TRUE;
9025 }
9026
9027 /* check whether rounding would lead to an unsatisfiable constraint */
9028 if( SCIPisGT(scip, newlhs, newrhs) )
9029 {
9030 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
9031 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
9032
9033 *infeasible = TRUE;
9034 return SCIP_OKAY;
9035 }
9036
9037 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
9038 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9039
9040 if( chglhs )
9041 {
9043
9044 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9045 if( !consdata->upgraded )
9046 (*nchgsides)++;
9047 }
9048 if( chgrhs )
9049 {
9051
9052 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9053 if( !consdata->upgraded )
9054 (*nchgsides)++;
9055 }
9056 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
9057 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9058 }
9059 }
9060
9061 return SCIP_OKAY;
9062}
9063
9064/** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
9065 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
9066 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
9067 * (i) ai >= 0:
9068 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
9069 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
9070 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9071 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9072 * - change coefficients:
9073 * ai' := max(lhs - minact, maxact - rhs)
9074 * lhs' := lhs - (ai - ai')*li
9075 * rhs' := rhs - (ai - ai')*ui
9076 * (ii) ai < 0:
9077 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9078 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9079 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9080 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9081 * - change coefficients:
9082 * ai' := min(rhs - maxact, minact - lhs)
9083 * lhs' := lhs - (ai - ai')*ui
9084 * rhs' := rhs - (ai - ai')*li
9085 *
9086 * We further try to remove redundant variable from the constraint;
9087 * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
9088 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9089 * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
9090 * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
9091 * 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
9092 * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
9093 *
9094 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9095 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9096 */
9097static
9099 SCIP* scip, /**< SCIP data structure */
9100 SCIP_CONS* cons, /**< linear constraint */
9101 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9102 int* nchgsides /**< pointer to count number of side changes */
9103 )
9104{
9105 SCIP_CONSDATA* consdata;
9106 SCIP_VAR* var;
9107 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9108 * activity, ignoring the coefficients contributing with infinite value */
9109 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9110 * activity, ignoring the coefficients contributing with infinite value */
9111 SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
9112 SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
9113 SCIP_Bool isminsettoinfinity;
9114 SCIP_Bool ismaxsettoinfinity;
9115 SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
9116 SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
9117 SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
9118 SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
9119 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9120 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9121 SCIP_Real val;
9122 SCIP_Real newval;
9123 SCIP_Real newlhs;
9124 SCIP_Real newrhs;
9125 SCIP_Real lb;
9126 SCIP_Real ub;
9127 int i;
9128
9129 assert(scip != NULL);
9130 assert(cons != NULL);
9131 assert(nchgcoefs != NULL);
9132 assert(nchgsides != NULL);
9133
9134 consdata = SCIPconsGetData(cons);
9135 assert(consdata != NULL);
9136
9137 /* @todo Is this still needed with automatic recomputation of activities? */
9138 /* if the maximal coefficient is too large, recompute the activities */
9139 if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9140 || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9141 {
9144 }
9145
9146 /* get the minimal and maximal activity of the constraint */
9147 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9149
9150 minleftactivity = 0.0;
9151 maxleftactivity = 0.0;
9152
9153 /* try to tighten each coefficient */
9154 i = 0;
9155 while( i < consdata->nvars )
9156 {
9157 var = consdata->vars[i];
9158
9159 /* get coefficient and variable's bounds */
9160 lb = SCIPvarGetLbLocal(var);
9161 ub = SCIPvarGetUbLocal(var);
9162 val = consdata->vals[i];
9163 assert(!SCIPisZero(scip, val));
9164
9165 /* check sign of coefficient */
9166 if( val >= 0.0 )
9167 {
9168 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9170 SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
9171 {
9172 /* change coefficients:
9173 * ai' := max(lhs - minact, maxact - rhs)
9174 * lhs' := lhs - (ai - ai')*li
9175 * rhs' := rhs - (ai - ai')*ui
9176 */
9177
9178 lval = consdata->lhs - minactivity;
9179 rval = maxactivity - consdata->rhs;
9180
9181 /* Try to avoid cancellation, if there are only two variables */
9182 if( consdata->nvars == 2 )
9183 {
9184 SCIP_Real otherval;
9185 otherval = consdata->vals[1-i];
9186
9187 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9188 {
9189 lval = consdata->lhs - val*lb;
9190 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9191 }
9192
9193 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9194 {
9195 rval = val*ub - consdata->rhs;
9196 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9197 }
9198 }
9199
9200 newval = MAX(lval, rval);
9201 assert(SCIPisSumRelLE(scip, newval, val));
9202
9203 /* Try to avoid cancellation in computation of lhs/rhs */
9204 newlhs = consdata->lhs - val * lb;
9205 newlhs += newval * lb;
9206 newrhs = consdata->rhs - val * ub;
9207 newrhs += newval * ub;
9208
9209 if( !SCIPisSumRelEQ(scip, newval, val) )
9210 {
9211 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9212 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9213 minactivity, maxactivity, consdata->lhs, consdata->rhs);
9214
9215 /* update the coefficient and the activity bounds */
9216 if( SCIPisZero(scip, newval) )
9217 {
9218 SCIP_CALL( delCoefPos(scip, cons, i) );
9219 i--;
9220 }
9221 else
9222 {
9223 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9224 }
9225 (*nchgcoefs)++;
9226
9227 /* get the new minimal and maximal activity of the constraint */
9228 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9230
9231 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9232 {
9233 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9234
9235 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9236 (*nchgsides)++;
9237 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9238 }
9239
9240 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9241 {
9242 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9243
9244 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9245 (*nchgsides)++;
9246 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9247 }
9248 }
9249 }
9250 else
9251 {
9253 {
9254 assert(!SCIPisInfinity(scip, val));
9255 assert(!SCIPisInfinity(scip, lb));
9256 if( SCIPisInfinity(scip, -lb) )
9258 else
9259 minleftactivity += val * lb;
9260 }
9261
9263 {
9264 assert(!SCIPisInfinity(scip, val));
9265 assert(!SCIPisInfinity(scip, -ub));
9266 if( SCIPisInfinity(scip,ub) )
9268 else
9269 maxleftactivity += val * ub;
9270 }
9271 }
9272 }
9273 else
9274 {
9275 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9277 SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9278 {
9279 /* change coefficients:
9280 * ai' := min(rhs - maxact, minact - lhs)
9281 * lhs' := lhs - (ai - ai')*ui
9282 * rhs' := rhs - (ai - ai')*li
9283 */
9284
9285 lval = minactivity - consdata->lhs;
9286 rval = consdata->rhs - maxactivity;
9287
9288 /* Try to avoid cancellation, if there are only two variables */
9289 if( consdata->nvars == 2 )
9290 {
9291 SCIP_Real otherval;
9292 otherval = consdata->vals[1-i];
9293
9294 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9295 {
9296 lval = val*ub - consdata->lhs;
9297 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9298 }
9299
9300 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9301 {
9302 rval = consdata->rhs - val*lb;
9303 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9304 }
9305 }
9306
9307 newval = MIN(lval, rval);
9308 assert(SCIPisSumRelGE(scip, newval, val));
9309
9310 /* Try to avoid cancellation in computation of lhs/rhs */
9311 newlhs = consdata->lhs - val * ub;
9312 newlhs += newval * ub;
9313 newrhs = consdata->rhs - val * lb;
9314 newrhs += newval * lb;
9315
9316 if( !SCIPisSumRelEQ(scip, newval, val) )
9317 {
9318 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9319 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9320 minactivity, maxactivity, consdata->lhs, consdata->rhs);
9321
9322 /* update the coefficient and the activity bounds */
9323 if( SCIPisZero(scip, newval) )
9324 {
9325 SCIP_CALL( delCoefPos(scip, cons, i) );
9326 i--;
9327 }
9328 else
9329 {
9330 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9331 }
9332 (*nchgcoefs)++;
9333
9334 /* get the new minimal and maximal activity of the constraint */
9335 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9337
9338 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9339 {
9340 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9341
9342 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9343 (*nchgsides)++;
9344 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9345 }
9346
9347 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9348 {
9349 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9350
9351 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9352 (*nchgsides)++;
9353 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9354 }
9355 }
9356 }
9357 else
9358 {
9360 {
9361 assert(!SCIPisInfinity(scip, -val));
9362 assert(!SCIPisInfinity(scip, -ub));
9363 if( SCIPisInfinity(scip, ub) )
9365 else
9366 minleftactivity += val * ub;
9367 }
9368
9370 {
9371 assert(!SCIPisInfinity(scip, -val));
9372 assert(!SCIPisInfinity(scip, lb));
9373 if( SCIPisInfinity(scip, -lb) )
9375 else
9376 maxleftactivity += val * lb;
9377 }
9378 }
9379 }
9380 ++i;
9381 }
9382
9383 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9384 minleftactivity, consdata->rhs);
9385 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9386 maxleftactivity, consdata->lhs);
9387
9388 /* minleft == \infty ==> minactivity == \infty */
9391
9392 /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9393 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9394 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9395 * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9396 */
9397 assert(!SCIPisInfinity(scip, minactivity));
9398 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9399 return SCIP_OKAY;
9400
9401 /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9402 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9403 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9404 * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9405 */
9406 assert(!SCIPisInfinity(scip, -maxactivity));
9407 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9408 return SCIP_OKAY;
9409
9410 /* correct lhs and rhs by min/max activity of surely non-redundant variables
9411 * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9412 */
9413 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9414 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9415
9416 /* check if the constraint contains variables which are redundant. The reasoning is the following:
9417 * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9418 * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9419 * they can be removed from the constraint.
9420 * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9421 */
9422 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9423 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9424 {
9425 SCIP_Real minleftactivitypart;
9426 SCIP_Real maxleftactivitypart;
9427
9428 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9429
9430 /* try to remove redundant variables from constraint */
9431 i = 0;
9432 while( i < consdata->nvars )
9433 {
9434 var = consdata->vars[i];
9435 minleftactivitypart = 0.0;
9436 maxleftactivitypart = 0.0;
9437 lb = SCIPvarGetLbLocal(var);
9438 ub = SCIPvarGetUbLocal(var);
9439
9440 /* get coefficient and variable's bounds */
9441 val = consdata->vals[i];
9442 assert(!SCIPisZero(scip, val));
9443
9444 /* check sign of coefficient */
9445 if( val >= 0.0 )
9446 {
9447 /* negation of condition above in case of positive val */
9449 SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9450 {
9451 SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9452 SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9453 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9454 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9455
9456 minleftactivitypart = val * lb;
9457 maxleftactivitypart = val * ub;
9458
9459 SCIP_CALL( delCoefPos(scip, cons, i) );
9460 i--;
9461
9462 /* get the new minimal and maximal activity of the constraint */
9463 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9465
9466 /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9467 * huge contributions
9468 */
9469 assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9470 assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9471 }
9472 }
9473 else
9474 {
9475 /* negation of condition above in case of negative val */
9477 SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9478 {
9479 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9480 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9481
9482 minleftactivitypart = val * ub;
9483 maxleftactivitypart = val * lb;
9484
9485 SCIP_CALL( delCoefPos(scip, cons, i) );
9486 i--;
9487
9488 /* get the new minimal and maximal activity of the constraint */
9489 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9491
9492 /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9493 * huge contributions
9494 */
9495 assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9496 assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9497 }
9498 }
9499
9500 /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9501 * redundant variables could get deleted,
9502 * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9503 * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9504 * we would also delete y2 and as a result we would have gotten infeasibility */
9505 /* adjust lhs and right hand side */
9506 newlhs = consdata->lhs - minleftactivitypart;
9507 newrhs = consdata->rhs - maxleftactivitypart;
9508
9509 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9510 {
9511 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9512 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9513 ++(*nchgsides);
9514 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9515 }
9516 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9517 {
9518 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9519 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9520 ++(*nchgsides);
9521 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9522 }
9523 ++i;
9524 }
9525 }
9526
9527 return SCIP_OKAY;
9528}
9529
9530/** processes equality with only one variable by fixing the variable and deleting the constraint */
9531static
9533 SCIP* scip, /**< SCIP data structure */
9534 SCIP_CONS* cons, /**< linear constraint */
9535 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9536 int* nfixedvars, /**< pointer to count number of fixed variables */
9537 int* ndelconss /**< pointer to count number of deleted constraints */
9538 )
9539{
9540 SCIP_CONSDATA* consdata;
9541 SCIP_VAR* var;
9542 SCIP_Real val;
9543 SCIP_Real fixval;
9544 SCIP_Bool infeasible;
9545 SCIP_Bool fixed;
9546
9547 assert(scip != NULL);
9548 assert(cons != NULL);
9549 assert(cutoff != NULL);
9550 assert(nfixedvars != NULL);
9551 assert(ndelconss != NULL);
9552
9553 consdata = SCIPconsGetData(cons);
9554 assert(consdata != NULL);
9555 assert(consdata->nvars == 1);
9556 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9557
9558 /* calculate the value to fix the variable to */
9559 var = consdata->vars[0];
9560 val = consdata->vals[0];
9561 assert(!SCIPisZero(scip, val));
9562 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9563 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9564 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9566
9567 /* fix variable */
9568 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9569 if( infeasible )
9570 {
9571 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9572 *cutoff = TRUE;
9573 return SCIP_OKAY;
9574 }
9575 if( fixed )
9576 (*nfixedvars)++;
9577
9578 /* disable constraint */
9579 SCIP_CALL( SCIPdelCons(scip, cons) );
9580 if( !consdata->upgraded )
9581 (*ndelconss)++;
9582
9583 return SCIP_OKAY;
9584}
9585
9586/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9587static
9589 SCIP* scip, /**< SCIP data structure */
9590 SCIP_CONS* cons, /**< linear constraint */
9591 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9592 int* naggrvars, /**< pointer to count number of aggregated variables */
9593 int* ndelconss /**< pointer to count number of deleted constraints */
9594 )
9595{
9596 SCIP_CONSDATA* consdata;
9597 SCIP_Bool infeasible;
9598 SCIP_Bool redundant;
9599 SCIP_Bool aggregated;
9600
9601 assert(scip != NULL);
9602 assert(cons != NULL);
9603 assert(cutoff != NULL);
9604 assert(naggrvars != NULL);
9605 assert(ndelconss != NULL);
9606
9607 consdata = SCIPconsGetData(cons);
9608 assert(consdata != NULL);
9609 assert(consdata->nvars == 2);
9610 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9611
9612 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9613 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9614 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9615
9616 /* aggregate the equality */
9617 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9618 consdata->rhs, &infeasible, &redundant, &aggregated) );
9619
9620 /* check for infeasibility of aggregation */
9621 if( infeasible )
9622 {
9623 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9624 *cutoff = TRUE;
9625 return SCIP_OKAY;
9626 }
9627
9628 /* count the aggregation */
9629 if( aggregated )
9630 (*naggrvars)++;
9631
9632 /* delete the constraint, if it is redundant */
9633 if( redundant )
9634 {
9635 SCIP_CALL( SCIPdelCons(scip, cons) );
9636
9637 if( !consdata->upgraded )
9638 (*ndelconss)++;
9639 }
9640
9641 return SCIP_OKAY;
9642}
9643
9644/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9645static
9647 SCIP* scip, /**< SCIP data structure */
9648 SCIP_CONSDATA* consdata, /**< linear constraint data */
9649 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9650 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9651 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9652 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9653 )
9654{
9655 SCIP_Real slackvarlb;
9656 SCIP_Real slackvarub;
9657
9658 assert(scip != NULL);
9659 assert(consdata != NULL);
9660 assert(newlhs != NULL);
9661 assert(newrhs != NULL);
9662 assert(!SCIPisInfinity(scip, -consdata->lhs));
9663 assert(!SCIPisInfinity(scip, consdata->rhs));
9664
9665 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9666 slackvarub = SCIPvarGetUbGlobal(slackvar);
9667 if( slackcoef > 0.0 )
9668 {
9671 else
9672 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9675 else
9676 *newlhs = consdata->lhs - slackcoef * slackvarub;
9677 }
9678 else
9679 {
9682 else
9683 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9686 else
9687 *newrhs = consdata->lhs - slackcoef * slackvarub;
9688 }
9690}
9691
9692/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9693 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9694 * is implicitly integral by this constraint
9695 *
9696 * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9697 * can help.
9698 */
9699static
9701 SCIP* scip, /**< SCIP data structure */
9702 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9703 SCIP_CONS* cons, /**< linear constraint */
9704 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9705 int* naggrvars, /**< pointer to count number of aggregated variables */
9706 int* ndelconss /**< pointer to count number of deleted constraints */
9707 )
9708{
9709 SCIP_CONSDATA* consdata;
9710 SCIP_VAR** vars;
9711 SCIP_Real* vals;
9714 SCIP_Real lhs;
9715 SCIP_Real rhs;
9716 SCIP_Real bestslackdomrng;
9717 SCIP_Real minabsval;
9718 SCIP_Real maxabsval;
9719 SCIP_Bool bestremovescons;
9720 SCIP_Bool coefszeroone;
9721 SCIP_Bool coefsintegral;
9722 SCIP_Bool varsintegral;
9723 SCIP_Bool infeasible;
9724 SCIP_Bool samevar;
9725 int supinf; /* counter for infinite contributions to the supremum of a possible
9726 * multi-aggregation
9727 */
9728 int infinf; /* counter for infinite contributions to the infimum of a possible
9729 * multi-aggregation
9730 */
9731 int maxnlocksstay;
9732 int maxnlocksremove;
9733 int bestslackpos;
9734 int bestnlocks;
9735 int ncontvars;
9736 int contvarpos;
9737 int nintvars;
9738 int nimplvars;
9739 int intvarpos;
9740 int v;
9741
9742 assert(scip != NULL);
9743 assert(cons != NULL);
9744 assert(cutoff != NULL);
9745 assert(naggrvars != NULL);
9746
9747 consdata = SCIPconsGetData(cons);
9748 assert(consdata != NULL);
9749 assert(consdata->nvars > 2);
9750 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9751
9752 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9753
9754 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9755 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9756 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9757 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9758 */
9759 lhs = consdata->lhs;
9760 rhs = consdata->rhs;
9761 maxnlocksstay = 0;
9762 if( consdata->nvars == 3 )
9763 {
9764 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9765 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9766 */
9767 maxnlocksremove = 3;
9768 }
9769 else if( consdata->nvars == 4 )
9770 {
9771 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9772 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9773 */
9774 maxnlocksremove = 2;
9775 }
9776 else
9777 {
9778 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9779 maxnlocksremove = 1;
9780 }
9781
9782 /* the locks on this constraint can be ignored */
9783 if( SCIPconsIsChecked(cons) )
9784 {
9785 if( !SCIPisInfinity(scip, -lhs) )
9786 {
9787 maxnlocksstay++;
9789 }
9790 if( !SCIPisInfinity(scip, rhs) )
9791 {
9792 maxnlocksstay++;
9794 }
9795 }
9796
9797 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9798 vars = consdata->vars;
9799 vals = consdata->vals;
9800 bestslackpos = -1;
9804 bestslackdomrng = 0.0;
9808 ncontvars = 0;
9809 contvarpos = -1;
9810 nintvars = 0;
9811 nimplvars = 0;
9812 intvarpos = -1;
9813 minabsval = SCIPinfinity(scip);
9814 maxabsval = -1.0;
9815 for( v = 0; v < consdata->nvars; ++v )
9816 {
9817 SCIP_VAR* var;
9818 SCIP_Real val;
9819 SCIP_Real absval;
9820 SCIP_Real varlb;
9821 SCIP_Real varub;
9822 SCIP_Bool iscont;
9823 int nlocks;
9824
9825 assert(vars != NULL);
9826 assert(vals != NULL);
9827
9828 var = vars[v];
9829 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9833
9834 val = vals[v];
9835 absval = REALABS(val);
9837
9838 /* calculate minimal and maximal absolute value */
9839 if( absval < minabsval )
9840 minabsval = absval;
9841 if( absval > maxabsval )
9842 maxabsval = absval;
9843
9844 /* do not try to multi aggregate, when numerical bad */
9845 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9846 return SCIP_OKAY;
9847
9853
9854 /* update candidates for continuous -> implint and integer -> implint conversion */
9856 {
9857 ncontvars++;
9858 contvarpos = v;
9859 }
9860 else if( slacktype == SCIP_VARTYPE_IMPLINT )
9861 {
9862 ++nimplvars;
9863 }
9864 else if( slacktype == SCIP_VARTYPE_INTEGER )
9865 {
9866 nintvars++;
9867 intvarpos = v;
9868 }
9869
9870 /* check, if variable is already fixed or aggregated */
9871 if( !SCIPvarIsActive(var) )
9872 continue;
9873
9874 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9876
9877 if( nlocks > maxnlocksremove )
9878 continue;
9879
9880 /* check, if variable can be used as a slack variable */
9881 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9883 {
9884 SCIP_Bool better;
9885 SCIP_Bool equal;
9886 SCIP_Real slackdomrng;
9887
9890 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9892 return SCIP_OKAY;
9893 else
9894 {
9897 }
9898 equal = FALSE;
9899 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9900 if( !better && slacktype == bestslacktype )
9901 {
9902 better = (nlocks < bestnlocks);
9903 if( nlocks == bestnlocks && !bestremovescons )
9904 {
9907 }
9908 }
9909
9910 if( better || equal )
9911 {
9912 SCIP_Real minresactivity;
9913 SCIP_Real maxresactivity;
9914 SCIP_Real newlhs;
9915 SCIP_Real newrhs;
9916 SCIP_Bool removescons;
9917 SCIP_Bool minisrelax;
9918 SCIP_Bool maxisrelax;
9919 SCIP_Bool isminsettoinfinity;
9920 SCIP_Bool ismaxsettoinfinity;
9921
9922 /* check if the constraint becomes redundant after multi-aggregation */
9925
9926 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9927 * activity
9928 */
9929 if( minisrelax || maxisrelax )
9930 continue;
9931
9932 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9934
9935 /* check resactivities for reliability */
9936 if( removescons )
9937 {
9938 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9940
9941 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9944
9946 }
9947
9948 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9949 if( conshdlrdata->multaggrremove && !removescons )
9950 continue;
9951
9952 /* prefer variables that make the constraints redundant */
9954 continue;
9955
9956 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9957 * other constraints
9958 */
9959 if( !removescons && nlocks > maxnlocksstay )
9960 continue;
9961
9963 if( better )
9964 {
9965 bestslackpos = v;
9967 bestnlocks = nlocks;
9970 }
9971 }
9972 }
9973 }
9974
9975 /* if all coefficients and variables are integral, the right hand side must also be integral */
9976 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9977 {
9978 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9980 *cutoff = TRUE;
9981 return SCIP_OKAY;
9982 }
9983
9984 supinf = 0;
9985 infinf = 0;
9986 samevar = FALSE;
9987
9988 /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9989 for( v = 0; v < consdata->nvars; ++v )
9990 {
9991 if( v != bestslackpos )
9992 {
9993 if( SCIPisPositive(scip, consdata->vals[v]) )
9994 {
9995 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9996 {
9997 ++supinf;
9998 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9999 {
10000 ++infinf;
10001 samevar = TRUE;
10002 }
10003 }
10004 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10005 ++infinf;
10006 }
10007 else if( SCIPisNegative(scip, consdata->vals[v]) )
10008 {
10009 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10010 {
10011 ++supinf;
10012 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10013 {
10014 ++infinf;
10015 samevar = TRUE;
10016 }
10017 }
10018 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10019 ++infinf;
10020 }
10021 }
10022 }
10023 assert(!samevar || (supinf > 0 && infinf > 0));
10024
10025 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10026 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10027 if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
10028 {
10029 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10030 return SCIP_OKAY;
10031 }
10032
10033 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
10034 * we cannot aggregate the variable, because the integrality condition would get lost
10035 * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
10036 * loose the integrality condition for this variable.
10037 */
10038 if( bestslackpos >= 0
10040 || (coefsintegral && varsintegral && nimplvars == 0)) )
10041 {
10042 SCIP_VAR* slackvar;
10043 SCIP_Real* scalars;
10044 SCIP_Real slackcoef;
10045 SCIP_Real aggrconst;
10046 SCIP_Real newlhs;
10047 SCIP_Real newrhs;
10048 SCIP_Bool aggregated;
10049
10050 /* we found a slack variable that only occurs in at most one other constraint:
10051 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
10052 */
10054
10055 /* do not multi aggregate binary variables */
10057 return SCIP_OKAY;
10058
10059 /* convert equality into inequality by deleting the slack variable:
10060 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
10061 */
10062 slackvar = vars[bestslackpos];
10063 slackcoef = vals[bestslackpos];
10065 aggrconst = consdata->rhs/slackcoef;
10066
10067 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
10069 SCIP_CALL( chgLhs(scip, cons, newlhs) );
10070 SCIP_CALL( chgRhs(scip, cons, newrhs) );
10072
10073 /* allocate temporary memory */
10074 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
10075
10076 /* set up the multi-aggregation */
10077 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
10078 for( v = 0; v < consdata->nvars; ++v )
10079 {
10080 scalars[v] = -consdata->vals[v]/slackcoef;
10081 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
10082 }
10083 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
10084 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
10086
10087 /* perform the multi-aggregation */
10088 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10089 &infeasible, &aggregated) );
10091
10092 /* free temporary memory */
10094
10095 /* check for infeasible aggregation */
10096 if( infeasible )
10097 {
10098 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10099 *cutoff = TRUE;
10100 return SCIP_OKAY;
10101 }
10102
10103 (*naggrvars)++;
10104
10105 /* delete the constraint if it became redundant */
10106 if( bestremovescons )
10107 {
10108 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10109 SCIP_CALL( SCIPdelCons(scip, cons) );
10110
10111 if( !consdata->upgraded )
10112 (*ndelconss)++;
10113 }
10114 }
10115 else if( ncontvars == 1 )
10116 {
10117 SCIP_VAR* var;
10118
10120 var = vars[contvarpos];
10122
10123 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10124 {
10125 /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10126 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10127 {
10128 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10129 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10132 if( infeasible )
10133 {
10134 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10135 *cutoff = TRUE;
10136
10137 return SCIP_OKAY;
10138 }
10139 }
10140 /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10141 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10142 else if( !SCIPdoNotAggr(scip) )
10143 {
10145 SCIP_Real absval;
10147 SCIP_Bool redundant;
10148 SCIP_Bool aggregated;
10149
10150 absval = REALABS(vals[contvarpos]);
10151
10153
10154 /* create new implicit variable for aggregation */
10157
10158 /* add new variable to problem */
10160
10161#ifdef WITH_DEBUG_SOLUTION
10163 {
10164 SCIP_Real varval;
10167 }
10168#endif
10169
10170 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10171 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10173
10174 /* aggregate continuous and implicit variable */
10175 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10176
10177 if( infeasible )
10178 {
10179 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10181 *cutoff = TRUE;
10182
10183 /* release implicit variable */
10185
10186 return SCIP_OKAY;
10187 }
10188
10189 /* release implicit variable */
10191
10192 if( aggregated )
10193 (*naggrvars)++;
10194 else
10195 return SCIP_OKAY;
10196 }
10197
10198 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10199 * again
10200 */
10201 consdata->boundstightened = 0;
10202 consdata->rangedrowpropagated = 0;
10203 consdata->presolved = FALSE;
10204 }
10205 }
10206 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10207 {
10208 SCIP_VAR* var;
10209
10210 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10211 * -> we don't convert integers into implints if the row is a 0/1-row
10212 */
10215 var = vars[intvarpos];
10217
10218 if( coefsintegral
10219 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10220 && SCIPisFeasIntegral(scip, consdata->rhs) )
10221 {
10222 /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10223 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10226 if( infeasible )
10227 {
10228 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10229 *cutoff = TRUE;
10230
10231 return SCIP_OKAY;
10232 }
10233 }
10234 }
10235
10236 return SCIP_OKAY;
10237}
10238
10239/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10240static
10242 SCIP* scip, /**< SCIP data structure */
10243 SCIP_CONSDATA* consdata, /**< linear constraint data */
10244 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10245 * objective function */
10246 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10247 * this constraint */
10248 )
10249{
10250 SCIP_VAR** vars;
10251 SCIP_VAR* var;
10252 SCIP_Real objval;
10253 SCIP_Bool negated;
10254 int nvars;
10255 int v;
10256
10257 vars = consdata->vars;
10258 nvars = consdata->nvars;
10259
10260 assert(vars != NULL);
10261
10262 for( v = 0; v < nvars; ++v )
10263 {
10264 negated = FALSE;
10265 var = vars[v];
10266 assert(var != NULL);
10267
10268 if( SCIPvarIsNegated(var) )
10269 {
10270 negated = TRUE;
10272 assert(var != NULL);
10273 }
10274
10276
10277 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10278 * function
10279 */
10280 if( SCIPisZero(scip, objval) )
10281 return FALSE;
10282 else
10283 {
10284 SCIP_Real val;
10285
10286 val = consdata->vals[v];
10287
10288 if( negated )
10289 {
10290 if( v == 0 )
10291 {
10292 /* the first variable defines the scale */
10293 (*scale) = val / -objval;
10294
10295 (*offset) += val;
10296 }
10297 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10298 (*offset) += val;
10299 else
10300 return FALSE;
10301 }
10302 else if( v == 0 )
10303 {
10304 /* the first variable defines the scale */
10305 (*scale) = val / objval;
10306 }
10307 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10308 return FALSE;
10309 }
10310 }
10311
10312 return TRUE;
10313}
10314
10315/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10316 * objective coefficients and add an objective offset
10317 */
10318static
10320 SCIP* scip, /**< SCIP data structure */
10321 SCIP_CONS* cons, /**< linear equation constraint */
10322 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10323 )
10324{
10325 SCIP_CONSDATA* consdata;
10326 SCIP_Real offset;
10327 SCIP_Real scale;
10328 SCIP_Bool applicable;
10329 int nobjvars;
10330 int nvars;
10331 int v;
10332
10333 assert(scip != NULL);
10334 assert(cons != NULL);
10335 assert(conshdlrdata != NULL);
10336
10337 consdata = SCIPconsGetData(cons);
10338 assert(consdata != NULL);
10339 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10340
10341 nvars = consdata->nvars;
10342 nobjvars = SCIPgetNObjVars(scip);
10343
10344 /* check if the linear equality constraints does not have more variables than the objective function */
10345 if( nvars > nobjvars || nvars == 0 )
10346 return SCIP_OKAY;
10347
10348 /* check for allowance of algorithm */
10349 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10350 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10351 return SCIP_OKAY;
10352
10353 offset = consdata->rhs;
10354 scale = 1.0;
10355
10356 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10357 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10358
10359 if( applicable )
10360 {
10361 SCIP_VAR** vars;
10362
10363 vars = consdata->vars;
10364 assert(vars != NULL);
10365
10366 offset /= scale;
10367
10368 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10369 SCIPconsGetName(cons), consdata->rhs, offset);
10370
10371 /* make equality a model constraint to ensure optimality in this direction */
10374
10375 /* set all objective coefficient to zero */
10376 for( v = 0; v < nvars; ++v )
10377 {
10378 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10379 }
10380
10381 /* add an objective offset */
10383 }
10384
10385 return SCIP_OKAY;
10386}
10387
10388/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10389static
10391 SCIP* scip, /**< SCIP data structure */
10392 SCIP_CONS* cons, /**< constraint */
10393 SCIP_Real primalbound /**< feasible primal bound */
10394 )
10395{
10396 SCIP_Real cutoffbound;
10397
10398 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10399 * accepted
10400 */
10401 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10402
10403 if( cutoffbound < SCIPgetCutoffbound(scip) )
10404 {
10405 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10406
10407 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10408 }
10409 else
10410 {
10411 SCIP_CONSDATA* consdata;
10412
10413 consdata = SCIPconsGetData(cons);
10414 assert(consdata != NULL);
10415
10416 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10417 * resulted from one side
10418 */
10419 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10420 {
10421 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10422 * propagation
10423 */
10426 }
10427 }
10428
10429 return SCIP_OKAY;
10430}
10431
10432/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10433 * constraint enters the LP by setting the initial and separated flag to FALSE
10434 */
10435static
10437 SCIP* scip, /**< SCIP data structure */
10438 SCIP_CONS* cons, /**< linear constraint */
10439 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10440 )
10441{
10442 SCIP_CONSDATA* consdata;
10443 SCIP_Real offset;
10444 SCIP_Real scale;
10445 SCIP_Bool applicable;
10446 int nobjvars;
10447 int nvars;
10448
10449 assert(scip != NULL);
10450 assert(cons != NULL);
10451 assert(conshdlrdata != NULL);
10452
10453 consdata = SCIPconsGetData(cons);
10454 assert(consdata != NULL);
10455
10456 /* ignore equalities since these are covered by the method checkPartialObjective() */
10457 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10458 return SCIP_OKAY;
10459
10460 nvars = consdata->nvars;
10461 nobjvars = SCIPgetNObjVars(scip);
10462
10463 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10464 * initial and/or separated flag is set to FALSE
10465 */
10466 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10467 return SCIP_OKAY;
10468
10469 offset = 0.0;
10470 scale = 1.0;
10471
10472 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10473 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10474 */
10475 if( nobjvars == 0 )
10476 return SCIP_OKAY;
10477
10478 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10479 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10480
10481 if( applicable )
10482 {
10483 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10484 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10485
10486 assert(scale != 0.0);
10487
10488 if( scale > 0.0 )
10489 {
10490 if( conshdlrdata->detectcutoffbound && rhsfinite )
10491 {
10492 SCIP_Real primalbound;
10493
10494 primalbound = (consdata->rhs - offset) / scale;
10495
10496 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10498
10500 }
10501
10502 if( conshdlrdata->detectlowerbound && lhsfinite )
10503 {
10504 SCIP_Real lowerbound;
10505
10506 lowerbound = (consdata->lhs - offset) / scale;
10507
10508 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10509 SCIPconsGetName(cons), lowerbound);
10510
10512 }
10513
10514 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10515 (conshdlrdata->detectlowerbound && !rhsfinite) )
10516 {
10517 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10520 }
10521 }
10522 else
10523 {
10524 if( conshdlrdata->detectlowerbound && rhsfinite )
10525 {
10526 SCIP_Real lowerbound;
10527
10528 lowerbound = (consdata->rhs - offset) / scale;
10529
10530 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10531 SCIPconsGetName(cons), lowerbound);
10532
10534 }
10535
10536 if( conshdlrdata->detectcutoffbound && lhsfinite )
10537 {
10538 SCIP_Real primalbound;
10539
10540 primalbound = (consdata->lhs - offset) / scale;
10541
10542 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10544
10546 }
10547
10548 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10549 (conshdlrdata->detectlowerbound && !lhsfinite) )
10550 {
10551 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10554 }
10555 }
10556 }
10557
10558 return SCIP_OKAY;
10559}
10560
10561/** converts special equalities */
10562static
10564 SCIP* scip, /**< SCIP data structure */
10565 SCIP_CONS* cons, /**< linear constraint */
10566 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10567 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10568 int* nfixedvars, /**< pointer to count number of fixed variables */
10569 int* naggrvars, /**< pointer to count number of aggregated variables */
10570 int* ndelconss /**< pointer to count number of deleted constraints */
10571 )
10572{
10573 SCIP_CONSDATA* consdata;
10574
10575 assert(scip != NULL);
10576 assert(cons != NULL);
10577 assert(conshdlrdata != NULL);
10578 assert(cutoff != NULL);
10579 assert(nfixedvars != NULL);
10580 assert(naggrvars != NULL);
10581 assert(ndelconss != NULL);
10582
10583 consdata = SCIPconsGetData(cons);
10584 assert(consdata != NULL);
10585 assert(consdata->removedfixings);
10586
10587 /* do nothing on inequalities */
10588 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10589 return SCIP_OKAY;
10590
10591 /* depending on the number of variables, call a special conversion method */
10592 if( consdata->nvars == 1 )
10593 {
10594 /* fix variable */
10595 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10596 }
10597 else if( consdata->nvars == 2 )
10598 {
10599 /* aggregate one of the variables */
10600 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10601 }
10602 else
10603 {
10604 /* check if the equality is part of the objective function */
10605 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10606
10607 /* try to multi-aggregate one of the variables */
10608 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10609 }
10610
10611 return SCIP_OKAY;
10612}
10613
10614/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10615 * integral
10616 */
10617static
10619 SCIP* scip, /**< SCIP data structure */
10620 SCIP_CONSDATA* consdata, /**< linear constraint */
10621 int pos, /**< position of variable to be left out */
10622 SCIP_Real val /**< value to divide the coefficients by */
10623 )
10624{
10625 int v;
10626
10627 assert(scip != NULL);
10628 assert(consdata != NULL);
10629 assert(0 <= pos && pos < consdata->nvars);
10630
10631 for( v = 0; v < consdata->nvars; ++v )
10632 {
10633 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10634 return FALSE;
10635 }
10636
10637 return TRUE;
10638}
10639
10640/** 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$,
10641 * 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$
10642 */
10643static
10645 SCIP* scip, /**< SCIP data structure */
10646 SCIP_Real side, /**< lhs or rhs */
10647 SCIP_Real val, /**< coefficient */
10648 SCIP_Real minresactivity, /**< minimal residual activity */
10649 SCIP_Real maxresactivity, /**< maximal residual activity */
10650 SCIP_Real* minval, /**< pointer to store calculated minval */
10651 SCIP_Real* maxval /**< pointer to store calculated maxval */
10652 )
10653{
10654 assert(scip != NULL);
10655 assert(minval != NULL);
10656 assert(maxval != NULL);
10657
10658 if( val > 0.0 )
10659 {
10661 *minval = -maxresactivity;
10662 else
10663 *minval = (side - maxresactivity)/val;
10664
10666 *maxval = -minresactivity;
10667 else
10668 *maxval = (side - minresactivity)/val;
10669 }
10670 else
10671 {
10673 *minval = minresactivity;
10674 else
10675 *minval = (side - minresactivity)/val;
10676
10678 *maxval = maxresactivity;
10679 else
10680 *maxval = (side - maxresactivity)/val;
10681 }
10682}
10683
10684
10685/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10686 * linear inequality
10687 */
10688static
10690 SCIP* scip, /**< SCIP data structure */
10691 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10692 SCIP_CONS* cons, /**< linear constraint */
10693 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10694 int* nfixedvars, /**< pointer to count number of fixed variables */
10695 int* naggrvars, /**< pointer to count number of aggregated variables */
10696 int* ndelconss /**< pointer to count number of deleted constraints */
10697 )
10698{
10699 SCIP_CONSDATA* consdata;
10700 SCIP_Bool lhsexists;
10701 SCIP_Bool rhsexists;
10702 SCIP_Bool bestisint;
10703 SCIP_Bool bestislhs;
10704 SCIP_Real minabsval;
10705 SCIP_Real maxabsval;
10706 int bestpos;
10707 int i;
10708 int maxotherlocks;
10709
10710 assert(scip != NULL);
10711 assert(cons != NULL);
10712 assert(cutoff != NULL);
10713 assert(nfixedvars != NULL);
10714 assert(naggrvars != NULL);
10715 assert(ndelconss != NULL);
10716
10717 /* only process checked constraints (for which the locks are increased);
10718 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10719 * dualfix presolver
10720 */
10721 if( !SCIPconsIsChecked(cons) )
10722 return SCIP_OKAY;
10723
10724 consdata = SCIPconsGetData(cons);
10725 assert(consdata != NULL);
10726
10727 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10728 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10729
10730 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10731 * can use it safely for aggregation and break the search loop
10732 */
10733 bestpos = -1;
10734 bestisint = TRUE;
10735 bestislhs = FALSE;
10736
10737 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10738 * everything else would produce fill-in. Exceptions:
10739 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10740 * produced.
10741 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10742 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10743 * six nonzeros (two variables per substitution).
10744 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10745 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10746 * six nonzeros (three variables per substitution). God exists!
10747 */
10748 if( consdata->nvars <= 2 )
10750 else if( consdata->nvars == 3 )
10751 maxotherlocks = 3;
10752 else if( consdata->nvars == 4 )
10753 maxotherlocks = 2;
10754 else
10755 maxotherlocks = 1;
10756
10757 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10759 maxotherlocks++;
10760
10761 minabsval = SCIPinfinity(scip);
10762 maxabsval = -1.0;
10763 for( i = 0; i < consdata->nvars && bestisint; ++i )
10764 {
10765 SCIP_VAR* var;
10766 SCIP_Bool isint;
10767 SCIP_Real val;
10768 SCIP_Real absval;
10769 SCIP_Real obj;
10770 SCIP_Real lb;
10771 SCIP_Real ub;
10772 SCIP_Bool agglhs;
10773 SCIP_Bool aggrhs;
10774
10775 val = consdata->vals[i];
10776 absval = REALABS(val);
10777
10778 /* calculate minimal and maximal absolute value */
10779 if( absval < minabsval )
10780 minabsval = absval;
10781 if( absval > maxabsval )
10782 maxabsval = absval;
10783
10784 /* do not try to multi aggregate, when numerical bad */
10785 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10786 return SCIP_OKAY;
10787
10788 var = consdata->vars[i];
10790
10791 /* if we already found a candidate, skip integers */
10792 if( bestpos >= 0 && isint )
10793 continue;
10794
10795 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10796 * active, fixed, or single-aggregated with another binary variable
10797 */
10798 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10799 continue;
10800
10802 continue;
10803
10804 val = consdata->vals[i];
10806 lb = SCIPvarGetLbGlobal(var);
10807 ub = SCIPvarGetUbGlobal(var);
10808
10809 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10810 *
10811 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10812 * - constraint is the only one that forbids fixing the variable to its lower bound
10813 * - 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
10814 *
10815 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10816 * - constraint is the only one that forbids fixing the variable to its upper bound
10817 * - 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
10818 *
10819 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10820 * - constraint is the only one that forbids fixing the variable to its upper bound
10821 * - 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
10822 *
10823 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10824 * - constraint is the only one that forbids fixing the variable to its lower bound
10825 * - 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
10826 *
10827 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10828 * of all x_j
10829 * furthermore: we only want to apply this, if no fill-in will be produced
10830 */
10841 if( agglhs || aggrhs )
10842 {
10843 SCIP_Real minresactivity;
10844 SCIP_Real maxresactivity;
10845 SCIP_Real minval;
10846 SCIP_Real maxval;
10847 SCIP_Bool minisrelax;
10848 SCIP_Bool maxisrelax;
10849 SCIP_Bool isminsettoinfinity;
10850 SCIP_Bool ismaxsettoinfinity;
10851
10852 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10856
10857 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10858 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10859 * This is needed, because we do not want to rely on relaxed finite resactivities.
10860 */
10862
10863 if( agglhs )
10864 {
10865 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10866 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10867
10868 assert(SCIPisLE(scip, minval, maxval));
10869 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10870 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10871 {
10872 SCIP_Real oldmaxresactivity;
10873 SCIP_Real oldminresactivity;
10874 SCIP_Bool recalculated;
10875
10879
10880 /* check minresactivity for reliability */
10881 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10882 {
10885 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10886 }
10887
10888 /* check maxresactivity for reliability */
10889 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10890 {
10893 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10894 }
10895
10896 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10897 if( recalculated )
10898 {
10900
10901 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10902 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10903
10904 assert(SCIPisLE(scip, minval, maxval));
10905 }
10906
10907 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10908 {
10909 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10910 * in the multi-aggregation
10911 */
10912 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10913 {
10914 bestpos = i;
10915 bestisint = isint;
10916 bestislhs = TRUE;
10917 continue; /* no need to also look at the right hand side */
10918 }
10919 }
10920 }
10921 }
10922
10923 if( aggrhs )
10924 {
10925 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10926 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10927
10928 assert(SCIPisLE(scip,minval,maxval));
10929 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10930 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10931 {
10932 SCIP_Real oldmaxresactivity;
10933 SCIP_Real oldminresactivity;
10934 SCIP_Bool recalculated;
10935
10939
10940 /* check minresactivity for reliability */
10941 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10942 {
10945 }
10946
10947 /* check maxresactivity for reliability */
10948 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10949 {
10952 }
10953
10954 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10955 if( recalculated )
10956 {
10957 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10958 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10959 assert(SCIPisLE(scip,minval,maxval));
10960 }
10961
10962 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10963 {
10964 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10965 * in the multi-aggregation
10966 */
10967 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10968 {
10969 bestpos = i;
10970 bestisint = isint;
10971 bestislhs = FALSE;
10972 }
10973 }
10974 }
10975 }
10976 }
10977 }
10978
10979 if( bestpos >= 0 )
10980 {
10982 SCIP_Real* aggrcoefs;
10983 SCIP_Real aggrconst;
10985 SCIP_Real bestval;
10986 SCIP_Real epsilon;
10987 int naggrs;
10988 int j;
10989 SCIP_Bool infeasible;
10990 SCIP_Bool aggregated;
10991 SCIP_Bool samevar;
10992 int supinf; /* counter for infinite contributions to the supremum of a possible
10993 * multi-aggregation
10994 */
10995 int infinf; /* counter for infinite contributions to the infimum of a possible
10996 * multi-aggregation
10997 */
10998
11001
11002 bestvar = consdata->vars[bestpos];
11003 bestval = consdata->vals[bestpos];
11004 assert(bestisint ==
11006
11007 /* allocate temporary memory */
11008 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
11009 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
11010
11011 /* set up the multi-aggregation */
11013 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
11014 naggrs = 0;
11015 supinf = 0;
11016 infinf = 0;
11017 samevar = FALSE;
11018 epsilon = SCIPepsilon(scip);
11019
11020 for( j = 0; j < consdata->nvars; ++j )
11021 {
11022 if( j != bestpos )
11023 {
11024 SCIP_Real absaggrcoef;
11025
11026 aggrvars[naggrs] = consdata->vars[j];
11027 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
11029
11031
11032 /* do not try to multi aggregate, when numerical bad */
11033 if( absaggrcoef < epsilon )
11034 {
11035 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
11036
11037 /* free temporary memory */
11040
11041 return SCIP_OKAY;
11042 }
11043
11044 if( bestisint )
11045 {
11046 /* coefficient must be integral: round it to exact integral value */
11049 }
11050
11052 {
11053 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11054 {
11055 ++supinf;
11056 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11057 {
11058 ++infinf;
11059 samevar = TRUE;
11060 }
11061 }
11062 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11063 ++infinf;
11064 }
11065 else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
11066 {
11067 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11068 {
11069 ++supinf;
11070 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11071 {
11072 ++infinf;
11073 samevar = TRUE;
11074 }
11075 }
11076 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11077 ++infinf;
11078 }
11079
11080 naggrs++;
11081 }
11082 }
11083 assert(!samevar || (supinf > 0 && infinf > 0));
11084
11085 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11086 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11088 assert(naggrs == consdata->nvars-1);
11089
11090 /* right hand side must be integral: round it to exact integral value */
11091 if( bestisint )
11092 {
11095 }
11096
11097 aggregated = FALSE;
11098 infeasible = FALSE;
11099
11100 /* perform the multi-aggregation */
11101 if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11102 {
11103 /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11104 * also convertLongEquality() early termination due to coefficients
11105 */
11107
11108 /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11109 * the implicitness might rely on the constraint and the integrality of bestvar
11110 */
11111 if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11112 {
11113 SCIP_Bool infeasiblevartypechg;
11114
11115 for( j = 0; j < naggrs; ++j)
11116 {
11117 /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11118 * lead to infeasibility
11119 */
11121 {
11124 }
11125 }
11126 }
11127 }
11128 else
11129 {
11130 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11131 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11132 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11133 }
11134 /* free temporary memory */
11137
11138 /* check for infeasible aggregation */
11139 if( infeasible )
11140 {
11141 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11142 *cutoff = TRUE;
11143 return SCIP_OKAY;
11144 }
11145
11146 /* delete the constraint, if the aggregation was successful */
11147 if( aggregated )
11148 {
11149 SCIP_CALL( SCIPdelCons(scip, cons) );
11150
11151 if( !consdata->upgraded )
11152 (*ndelconss)++;
11153 (*naggrvars)++;
11154 }
11155 else
11156 {
11157 SCIPdebugMsg(scip, "aggregation non successful!\n");
11158 }
11159 }
11160
11161 return SCIP_OKAY;
11162}
11163
11164#define BINWEIGHT 1
11165#define INTWEIGHT 4
11166#define CONTWEIGHT 8
11167
11168/** gets weight for variable in a "weighted number of variables" sum */
11169static
11171 SCIP_VAR* var /**< variable to get weight for */
11172 )
11173{
11174 switch( SCIPvarGetType(var) )
11175 {
11177 return BINWEIGHT;
11180 return INTWEIGHT;
11182 return CONTWEIGHT;
11183 default:
11184 SCIPerrorMessage("invalid variable type\n");
11185 SCIPABORT();
11186 return 0; /*lint !e527*/
11187 }
11188}
11189
11190/** tries to aggregate variables in equations a^Tx = lhs
11191 * in case there are at most two binary variables with an odd coefficient and all other
11192 * variables are not continuous and have an even coefficient then:
11193 * - exactly one odd binary variables
11194 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11195 * - lhs is odd -> y = 1
11196 * - lhs is even -> y = 0
11197 * - exactly two odd binary variables
11198 * aggregate the two binary variables with odd coefficient
11199 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11200 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11201 */
11202static
11204 SCIP* scip, /**< SCIP data structure */
11205 SCIP_CONS* cons, /**< linear constraint */
11206 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11207 int* nfixedvars, /**< pointer to count number of fixed variables */
11208 int* naggrvars /**< pointer to count number of aggregated variables */
11209 )
11210{ /*lint --e{715}*/
11211 SCIP_CONSDATA* consdata;
11212 SCIP_Bool success;
11213
11214 assert( scip != NULL );
11215 assert( cons != NULL );
11216
11217 consdata = SCIPconsGetData(cons);
11218 assert( consdata != NULL );
11219
11220 /* check if the linear constraint is an equation with integral right hand side */
11221 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11222 return SCIP_OKAY;
11223
11224 /* try to fix and aggregated variables until nothing is possible anymore */
11225 do
11226 {
11227 int v;
11228 int nvars;
11229 SCIP_VAR** vars;
11230 SCIP_Real* vals;
11231 SCIP_Real lhs;
11232 SCIP_Bool lhsodd;
11233
11234 SCIP_Bool infeasible;
11235 SCIP_Bool fixed;
11236 SCIP_Bool aggregated;
11237 SCIP_Bool redundant;
11238
11239 SCIP_VAR* var1;
11240 SCIP_VAR* var2;
11241 int noddvars;
11242
11243 success = FALSE;
11244
11245 lhs = consdata->lhs;
11246 vars = consdata->vars;
11247 vals = consdata->vals;
11248 nvars = consdata->nvars;
11249
11250 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11251
11252 var1 = NULL;
11253 var2 = NULL;
11254 noddvars = 0;
11255
11256 /* search for binary variables with an odd coefficient */
11257 for( v = 0; v < nvars && noddvars < 3; ++v )
11258 {
11259 SCIP_Longint val;
11260
11261 /* all coefficients and variables have to be integral */
11263 return SCIP_OKAY;
11264
11265 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11266 if( val % 2 != 0 )
11267 {
11268 /* the odd values have to belong to binary variables */
11269 if( !SCIPvarIsBinary(vars[v]) )
11270 return SCIP_OKAY;
11271
11272 if( noddvars == 0 )
11273 var1 = vars[v];
11274 else
11275 var2 = vars[v];
11276
11277 noddvars++;
11278 }
11279 }
11280
11281 /* check lhs is odd or even */
11282 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11283
11284 if( noddvars == 1 )
11285 {
11286 assert( var1 != NULL );
11287
11288 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11289 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11290
11291 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11292
11293 /* check for infeasibility of fixing */
11294 if( infeasible )
11295 {
11296 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11297 *cutoff = TRUE;
11298 return SCIP_OKAY;
11299 }
11300
11301 if( fixed )
11302 {
11303 SCIPdebugMsg(scip, " -> feasible fixing\n");
11304 (*nfixedvars)++;
11305 success = TRUE;
11306 }
11307 }
11308 else if( noddvars == 2 )
11309 {
11310 assert( var1 != NULL );
11311 assert( var2 != NULL );
11312
11313 /* aggregate the two variables with odd coefficient
11314 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11315 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11316 */
11317 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11319
11320 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11321 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11322
11323 /* check for infeasibility of aggregation */
11324 if( infeasible )
11325 {
11326 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11327 *cutoff = TRUE;
11328 return SCIP_OKAY;
11329 }
11330
11331 /* count the aggregation */
11332 if( aggregated )
11333 {
11334 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11335 (*naggrvars)++;
11336 success = TRUE;
11337 }
11338 }
11339
11340 if( success )
11341 {
11342 /* apply fixings and aggregation to successfully rerun this presolving step */
11343 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11344
11345 if( infeasible )
11346 {
11347 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11348 *cutoff = TRUE;
11349 return SCIP_OKAY;
11350 }
11351
11352 /* normalize constraint */
11353 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11354
11355 if( infeasible )
11356 {
11357 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11358 *cutoff = TRUE;
11359 return SCIP_OKAY;
11360 }
11361 }
11362 }
11363 while( success );
11364
11365 return SCIP_OKAY;
11366}
11367
11368
11369
11370/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11371 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11372 * coefficients
11373 */
11374static
11376{ /*lint --e{715}*/
11377 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11380 SCIP_Real value;
11381
11382 assert(consdata != NULL);
11385
11386 vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11387 vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11388
11390 {
11391 /* continuous varibles will be sorted to the back */
11392 if( vartype2 != vartype1 )
11393 return +1;
11394 /* both variables are continuous */
11395 else
11396 return 0;
11397 }
11398 /* continuous variables will be sorted to the back */
11399 else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11400 return -1;
11401
11402 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11403
11404 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11405 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11406}
11407
11408/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11409 *
11410 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11411 * then we can change this constraint to 1^Tx = 1
11412 */
11413static
11415 SCIP* scip, /**< SCIP data structure */
11416 SCIP_CONS* cons, /**< linear constraint */
11417 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11418 int* nchgsides /**< pointer to store the amount of changed sides */
11419 )
11420{
11421 SCIP_CONSDATA* consdata;
11422 SCIP_VAR** vars;
11423 SCIP_Real* vals;
11424 SCIP_Real minval;
11425 SCIP_Real secondminval;
11426 SCIP_Real maxval;
11427 SCIP_Real lhs;
11428 SCIP_Real rhs;
11429 int nvars;
11430 int v;
11431
11432 /* we must not change a modifiable constraint in any way */
11433 if( SCIPconsIsModifiable(cons) )
11434 return SCIP_OKAY;
11435
11436 if( SCIPconsIsDeleted(cons) )
11437 return SCIP_OKAY;
11438
11439 consdata = SCIPconsGetData(cons);
11440 assert(consdata != NULL);
11441
11442 nvars = consdata->nvars;
11443
11444 /* do not check empty or bound-constraints */
11445 if( nvars < 2 )
11446 return SCIP_OKAY;
11447
11448 lhs = consdata->lhs;
11449 rhs = consdata->rhs;
11450 assert(!SCIPisInfinity(scip, -lhs));
11451 assert(!SCIPisInfinity(scip, rhs));
11452 assert(!SCIPisNegative(scip, rhs));
11453
11454 /* sides must be positive and different to detect set partition */
11455 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11456 return SCIP_OKAY;
11457
11458 vals = consdata->vals;
11459 vars = consdata->vars;
11460 assert(vars != NULL);
11461 assert(vals != NULL);
11462
11463 minval = SCIP_INVALID;
11465 maxval = -SCIP_INVALID;
11466
11467 for( v = nvars - 1; v >= 0; --v )
11468 {
11469 if( SCIPvarIsBinary(vars[v]) )
11470 {
11471 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11472 {
11473 secondminval = minval;
11474 minval = vals[v];
11475 }
11476 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11477 secondminval = vals[v];
11478
11479 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11480 maxval = vals[v];
11481 }
11482 else
11483 break;
11484 }
11485
11486 /* check if all variables are binary, we can choose one, and need to choose at most one */
11487 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11488 && SCIPisGT(scip, minval + secondminval, rhs) )
11489 {
11490 /* change all coefficients to 1.0 */
11491 for( v = nvars - 1; v >= 0; --v )
11492 {
11493 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11494 }
11495 (*nchgcoefs) += nvars;
11496
11497 /* replace old right and left hand side with 1.0 */
11498 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11499 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11500 (*nchgsides) += 2;
11501 }
11502
11503 return SCIP_OKAY;
11504}
11505
11506/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11507 *
11508 * for both-sided constraints only @see rangedRowSimplify() will be called
11509 *
11510 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11511 *
11512 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11513 *
11514 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11515 *
11516 * 2. We try to remove redundant fractional parts in a constraint
11517 *
11518 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11519 *
11520 * 3. We are using the greatest common divisor for further reductions
11521 *
11522 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11523 * integral
11524 */
11525static
11527 SCIP* scip, /**< SCIP data structure */
11528 SCIP_CONS* cons, /**< linear constraint */
11529 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11530 int* nchgsides, /**< pointer to store the amount of changed sides */
11531 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11532 )
11533{
11534 SCIP_CONSDATA* consdata;
11535 SCIP_VAR** vars;
11536 SCIP_Real* vals;
11537 int* perm;
11538 SCIP_Real minactsub;
11539 SCIP_Real maxactsub;
11540 SCIP_Real siderest;
11541 SCIP_Real feastol;
11542 SCIP_Real newcoef;
11543 SCIP_Real absval;
11544 SCIP_Real minact;
11545 SCIP_Real maxact;
11546 SCIP_Real side;
11547 SCIP_Real lhs;
11548 SCIP_Real rhs;
11549 SCIP_Real lb;
11550 SCIP_Real ub;
11551 SCIP_Longint restcoef;
11552 SCIP_Longint oldgcd;
11553 SCIP_Longint rest;
11554 SCIP_Longint gcd;
11555 SCIP_Bool isminsettoinfinity;
11556 SCIP_Bool ismaxsettoinfinity;
11557 SCIP_Bool isminrelax;
11558 SCIP_Bool ismaxrelax;
11559 SCIP_Bool allcoefintegral;
11560 SCIP_Bool onlybin;
11561 SCIP_Bool hasrhs;
11562 SCIP_Bool haslhs;
11563 int oldnchgcoefs;
11564 int oldnchgsides;
11565 int foundbin;
11566 int candpos;
11567 int candpos2;
11568 int offsetv;
11569 int nvars;
11570 int v;
11571 int w;
11572
11573 assert(scip != NULL);
11574 assert(cons != NULL);
11575 assert(nchgcoefs != NULL);
11576 assert(nchgsides != NULL);
11577
11578 *infeasible = FALSE;
11579
11580 /* we must not change a modifiable constraint in any way */
11581 if( SCIPconsIsModifiable(cons) )
11582 return SCIP_OKAY;
11583
11584 if( SCIPconsIsDeleted(cons) )
11585 return SCIP_OKAY;
11586
11587 consdata = SCIPconsGetData(cons);
11588 assert(consdata != NULL);
11589
11590 nvars = consdata->nvars;
11591
11592 /* do not check empty or bound-constraints */
11593 if( nvars <= 2 )
11594 return SCIP_OKAY;
11595
11596 /* update maximal activity delta if necessary */
11597 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11599
11600 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11601 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11602 checkMaxActivityDelta(scip, consdata);
11603
11604 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11605 * accordingly
11606 */
11607 /* can only work with valid non-infinity activities per variable */
11608 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11609 return SCIP_OKAY;
11610
11611 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11612 * but the eventsystem seems to be full
11613 */
11614 consdata->normalized = FALSE;
11615
11616 /* normalize constraint */
11617 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11618 assert(nvars == consdata->nvars);
11619
11620 if( *infeasible )
11621 return SCIP_OKAY;
11622
11623 if( !consdata->normalized )
11624 return SCIP_OKAY;
11625
11626 lhs = consdata->lhs;
11627 rhs = consdata->rhs;
11628 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11629 assert(!SCIPisNegative(scip, rhs));
11630
11631 if( !SCIPisInfinity(scip, -lhs) )
11632 haslhs = TRUE;
11633 else
11634 haslhs = FALSE;
11635
11636 if( !SCIPisInfinity(scip, rhs) )
11637 hasrhs = TRUE;
11638 else
11639 hasrhs = FALSE;
11640
11641 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11642 SCIPdebug( oldnchgsides = *nchgsides; )
11643
11644 /* @todo extend both-sided simplification */
11645 if( haslhs && hasrhs )
11646 {
11647 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11648
11649 return SCIP_OKAY;
11650 }
11651 assert(haslhs != hasrhs);
11652
11653 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11654 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11655 assert(!haslhs || !SCIPisNegative(scip, lhs));
11656
11657 /* get temporary memory to store the sorted permutation */
11659
11660 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11661 * value of their coefficients
11662 */
11663 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11664
11665 /* perform sorting after permutation array */
11666 permSortConsdata(consdata, perm, nvars);
11667 consdata->indexsorted = FALSE;
11668 consdata->coefsorted = FALSE;
11669
11670 vars = consdata->vars;
11671 vals = consdata->vals;
11672 assert(vars != NULL);
11673 assert(vals != NULL);
11674 assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11675
11676 /* free temporary memory */
11677 SCIPfreeBufferArray(scip, &perm);
11678
11679 /* only check constraints with at least two non continuous variables */
11681 return SCIP_OKAY;
11682
11683 /* do not process constraints when all coefficients are 1.0 */
11684 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11685 return SCIP_OKAY;
11686
11687 feastol = SCIPfeastol(scip);
11688
11689 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11691
11692 /* get global activities */
11695
11696 /* cannot work with infinite activities */
11698 return SCIP_OKAY;
11699
11702 assert(maxact > minact);
11705
11706 v = 0;
11707 offsetv = -1;
11708 side = haslhs ? lhs : rhs;
11709 minactsub = minact;
11710 maxactsub = maxact;
11711
11712 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11713 * do not need to look at the large coefficients
11714 *
11715 * e.g. all x are binary, z are positive integer
11716 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11717 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11718 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11719 *
11720 * can be changed to
11721 *
11722 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11723 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11724 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11725 */
11726
11727 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11728 * hand side, we cannot apply the extra reduction step and need to reset v
11729 *
11730 * 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
11731 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11732 * for all i is a solution
11733 *
11734 * also redundancy of variables would not be correctly determined in such a case
11735 */
11736 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11737 {
11738 v = 1;
11739
11740 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11741 {
11742 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11743 * extra step, which might have worked
11744 */
11745 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11746 {
11747 v = 0;
11748 break;
11749 }
11750
11751 ++v;
11752 }
11753
11754 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11755 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11756 if( v == nvars )
11757 return SCIP_OKAY;
11758
11759 /* cannot work with continuous variables which have a big coefficient */
11760 if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11761 return SCIP_OKAY;
11762
11763 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11764 if( SCIPisEQ(scip, side, -vals[v]) )
11765 v = 0;
11766
11767 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11768 * reduction
11769 */
11770 if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11771 v = 0;
11772
11773 if( v > 0 )
11774 {
11775 assert(v < nvars);
11776
11777 offsetv = v - 1;
11778
11779 for( w = 0; w < v; ++w )
11780 {
11781 lb = SCIPvarGetLbGlobal(vars[w]);
11782 ub = SCIPvarGetUbGlobal(vars[w]);
11783
11784 assert(vals[w] > 0);
11785
11786 /* update residual activities */
11787 maxactsub -= ub * vals[w];
11788 minactsub -= lb * vals[w];
11790 }
11791 }
11792 }
11793
11794 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11795 *
11796 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11797 *
11798 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11799 * to
11800 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11801 */
11802 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11803 {
11804 SCIP_Bool redundant = FALSE;
11805 SCIP_Bool numericsok;
11806 SCIP_Bool rredundant;
11807 SCIP_Bool lredundant;
11808
11809 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11810 assert(gcd >= 1);
11811
11812 if( v == 0 )
11813 {
11814 lb = SCIPvarGetLbGlobal(vars[0]);
11815 ub = SCIPvarGetUbGlobal(vars[0]);
11816
11817 /* update residual activities */
11818 if( vals[0] > 0 )
11819 {
11820 maxactsub -= ub * vals[0];
11821 minactsub -= lb * vals[0];
11822 }
11823 else
11824 {
11825 maxactsub -= lb * vals[0];
11826 minactsub -= ub * vals[0];
11827 }
11829 ++v;
11830 }
11831
11834
11835 /* check if some variables always fit into the given constraint */
11836 for( ; v < nvars - 1; ++v )
11837 {
11839 break;
11840
11841 if( !SCIPisIntegral(scip, vals[v]) )
11842 {
11844 break;
11845 }
11846
11847 /* calculate greatest common divisor for all general and binary variables */
11848 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11849
11850 if( gcd == 1 )
11851 break;
11852
11853 lb = SCIPvarGetLbGlobal(vars[v]);
11854 ub = SCIPvarGetUbGlobal(vars[v]);
11855
11856 assert(!SCIPisInfinity(scip, -lb));
11857 assert(!SCIPisInfinity(scip, ub));
11858
11859 /* update residual activities */
11860 if( vals[v] > 0 )
11861 {
11862 maxactsub -= ub * vals[v];
11863 minactsub -= lb * vals[v];
11864 }
11865 else
11866 {
11867 maxactsub -= lb * vals[v];
11868 minactsub -= ub * vals[v];
11869 }
11871
11872 if( hasrhs )
11873 {
11874 /* determine the remainder of the right hand side and the gcd */
11875 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11876 }
11877 else
11878 {
11879 /* determine the remainder of the left hand side and the gcd */
11880 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11881 if( SCIPisZero(scip, siderest) )
11882 siderest = gcd;
11883 }
11884
11887
11888 /* early termination if the activities deceed the gcd */
11889 if( offsetv == -1 && (rredundant || lredundant) )
11890 {
11891 redundant = TRUE;
11892 break;
11893 }
11894 }
11895 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11896
11897 if( !redundant )
11898 {
11899 if( hasrhs )
11900 {
11901 /* determine the remainder of the right hand side and the gcd */
11902 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11903 }
11904 else
11905 {
11906 /* determine the remainder of the left hand side and the gcd */
11907 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11908 if( SCIPisZero(scip, siderest) )
11909 siderest = gcd;
11910 }
11911 }
11912 else
11913 ++v;
11914
11915 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",
11916 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11917
11918 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11919 * reasonable absolute values */
11922
11925
11926 /* check if we can remove redundant variables */
11927 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11928 {
11929 SCIP_Real oldcoef;
11930
11931 /* double check the redundancy */
11932#ifndef NDEBUG
11933 SCIP_Real tmpminactsub = 0.0;
11934 SCIP_Real tmpmaxactsub = 0.0;
11935
11936 /* recompute residual activities */
11937 for( w = v; w < nvars; ++w )
11938 {
11939 lb = SCIPvarGetLbGlobal(vars[w]);
11940 ub = SCIPvarGetUbGlobal(vars[w]);
11941
11942 assert(!SCIPisInfinity(scip, -lb));
11943 assert(!SCIPisInfinity(scip, ub));
11944
11945 /* update residual activities */
11946 if( vals[w] > 0 )
11947 {
11948 tmpmaxactsub += ub * vals[w];
11949 tmpminactsub += lb * vals[w];
11950 }
11951 else
11952 {
11953 tmpmaxactsub += lb * vals[w];
11954 tmpminactsub += ub * vals[w];
11955 }
11957 }
11958
11959 if( hasrhs )
11960 {
11961 assert(offsetv == -1);
11962
11963 /* determine the remainder of the right hand side and the gcd */
11964 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11965 }
11966 else
11967 {
11968 /* determine the remainder of the left hand side and the gcd */
11969 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11970 if( SCIPisZero(scip, siderest) )
11971 siderest = gcd;
11972 }
11973
11974 /* is the redundancy really fulfilled */
11977#endif
11978
11979 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11980 nvars - v, SCIPconsGetName(cons));
11981
11982 /* remove redundant variables */
11983 for( w = nvars - 1; w >= v; --w )
11984 {
11985 SCIP_CALL( delCoefPos(scip, cons, w) );
11986 }
11987 (*nchgcoefs) += (nvars - v);
11988
11989 assert(w >= 0);
11990
11991 oldcoef = vals[w];
11992
11993 /* normalize constraint */
11994 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11995 assert(vars == consdata->vars);
11996 assert(vals == consdata->vals);
11998
11999 if( *infeasible )
12000 return SCIP_OKAY;
12001
12002 /* compute new greatest common divisor due to normalization */
12003 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
12004 assert(gcd >= 1);
12005
12006 /* update side */
12007 if( hasrhs )
12008 {
12009 /* replace old with new right hand side */
12010 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
12011 rhs = consdata->rhs;
12012 }
12013 else
12014 {
12015 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
12016 {
12017 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
12018 lhs = consdata->lhs;
12019 }
12020 else
12021 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
12022 }
12023 ++(*nchgsides);
12024
12025 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12026 assert(!haslhs || !SCIPisNegative(scip, lhs));
12027
12028 /* get new constraint data */
12029 nvars = consdata->nvars;
12030 assert(nvars > 0);
12031
12033
12034#ifndef NDEBUG
12035 /* check integrality */
12036 for( w = offsetv + 1; w < nvars; ++w )
12037 {
12038 assert(SCIPisIntegral(scip, vals[w]));
12039 }
12040#endif
12042 }
12043
12044 /* try to find a better gcd, when having large coefficients */
12045 if( offsetv >= 0 && gcd == 1 )
12046 {
12047 /* calculate greatest common divisor for all general variables */
12048 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
12049
12050 if( gcd > 1 )
12051 {
12052 gcd = -1;
12053 candpos = -1;
12054
12055 for( v = nvars - 1; v > offsetv; --v )
12056 {
12057 assert(!SCIPisZero(scip, vals[v]));
12059 break;
12060
12061 if( !SCIPisIntegral(scip, vals[v]) )
12062 {
12064 break;
12065 }
12066
12067 oldgcd = gcd;
12068
12069 if( gcd == -1 )
12070 {
12071 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12072 assert(gcd >= 1);
12073 }
12074 else
12075 {
12076 /* calculate greatest common divisor for all general and binary variables */
12077 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12078 }
12079
12080 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12081 * can stop searching
12082 */
12083 if( gcd == 1 )
12084 {
12085 if( !SCIPvarIsBinary(vars[v]) )
12086 break;
12087
12088 /* found candidate */
12089 if( candpos == -1 )
12090 {
12091 gcd = oldgcd;
12092 candpos = v;
12093 }
12094 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12095 else
12096 break;
12097 }
12098 }
12099 assert(v > offsetv || candpos > offsetv);
12100 }
12101 else
12102 candpos = -1;
12103 }
12104 else
12105 candpos = nvars - 1;
12106
12107 /* check last coefficient for integrality */
12108 if( gcd > 1 && allcoefintegral && !redundant )
12109 {
12110 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12112 }
12113
12114 /* check for further necessary coefficient adjustments */
12115 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12116 {
12117 assert(offsetv + 1 < nvars);
12118 assert(0 <= candpos && candpos < nvars);
12119
12121 {
12122 SCIP_Bool notchangable = FALSE;
12123
12124#ifndef NDEBUG
12125 /* check integrality */
12126 for( w = offsetv + 1; w < nvars; ++w )
12127 {
12128 assert(SCIPisIntegral(scip, vals[w]));
12129 }
12130#endif
12131
12132 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12133 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12134 {
12135 /* determine the remainder of the side and the gcd */
12136 if( hasrhs )
12137 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12138 else
12139 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12140 assert(rest >= 0);
12141 assert(rest < gcd);
12142
12143 /* determine the remainder of the coefficient candidate and the gcd */
12144 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12145 assert(restcoef >= 1);
12146 assert(restcoef < gcd);
12147
12148 if( hasrhs )
12149 {
12150 /* calculate new coefficient */
12151 if( restcoef > rest )
12152 newcoef = vals[candpos] - restcoef + gcd;
12153 else
12154 newcoef = vals[candpos] - restcoef;
12155 }
12156 else
12157 {
12158 /* calculate new coefficient */
12159 if( rest == 0 || restcoef < rest )
12160 newcoef = vals[candpos] - restcoef;
12161 else
12162 newcoef = vals[candpos] - restcoef + gcd;
12163 }
12164
12165 /* done */
12166
12167 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12168 * another with the big coefficient was set to 1
12169 */
12170 if( hasrhs && SCIPisZero(scip, newcoef) )
12171 {
12173 }
12174 else if( SCIPisZero(scip, newcoef) )
12175 {
12176 /* delete old redundant coefficient */
12177 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12178 ++(*nchgcoefs);
12179 }
12180 else
12181 {
12182 /* replace old with new coefficient */
12184 ++(*nchgcoefs);
12185 }
12186 }
12187 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12188 {
12189 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12190 }
12191
12192 /* correct side and big coefficients */
12193 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12194 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12195 {
12196 if( haslhs )
12197 {
12198 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12199
12200 SCIP_CALL( chgLhs(scip, cons, newcoef) );
12201 ++(*nchgsides);
12202 }
12203 else
12204 {
12205 assert(hasrhs);
12206 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12207
12208 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12209 ++(*nchgsides);
12210 }
12211
12212 /* correct coefficients up front */
12213 for( w = offsetv; w >= 0; --w )
12214 {
12215 assert(vals[w] > 0);
12216
12217 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12218 }
12219 (*nchgcoefs) += (offsetv + 1);
12220 }
12221
12222 if( !notchangable )
12223 {
12224 /* normalize constraint */
12225 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12226 assert(vars == consdata->vars);
12227 assert(vals == consdata->vals);
12228
12229 if( *infeasible )
12230 return SCIP_OKAY;
12231
12232 /* get new constraint data */
12233 nvars = consdata->nvars;
12234 assert(nvars >= 2);
12235
12237
12238 lhs = consdata->lhs;
12239 rhs = consdata->rhs;
12240 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12241 assert(!haslhs || !SCIPisNegative(scip, lhs));
12242 }
12243 }
12244 }
12245 }
12246
12247 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12248 /* no continuous variables are left over */
12250 return SCIP_OKAY;
12251
12252 onlybin = TRUE;
12254 /* check if all variables are of binary type */
12255 for( v = nvars - 1; v >= 0; --v )
12256 {
12257 if( !SCIPvarIsBinary(vars[v]) )
12258 onlybin = FALSE;
12259 if( !SCIPisIntegral(scip, vals[v]) )
12261 }
12262
12263 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12264 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12265 *
12266 * @todo there are some steps missing ....
12267 */
12268 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12269 {
12270 SCIP_Real val;
12271 SCIP_Real newval;
12272 SCIP_Real frac = 0.0;
12273 SCIP_Bool found = FALSE;
12274
12275 if( hasrhs )
12276 {
12277 if( allcoefintegral )
12278 {
12279 /* replace old with new right hand side */
12280 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12281 ++(*nchgsides);
12282 }
12283 else
12284 {
12285 siderest = rhs - SCIPfloor(scip, rhs);
12286
12287 /* try to round down all non-integral coefficients */
12288 for( v = nvars - 1; v >= 0; --v )
12289 {
12290 val = vals[v];
12291
12292 /* add up all possible fractional parts */
12293 if( !SCIPisIntegral(scip, val) )
12294 {
12295 lb = SCIPvarGetLbGlobal(vars[v]);
12296 ub = SCIPvarGetUbGlobal(vars[v]);
12297
12298 /* at least one bound need to be at zero */
12299 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12300 return SCIP_OKAY;
12301
12302 /* swap bounds for 'standard' form */
12303 if( !SCIPisFeasZero(scip, lb) )
12304 {
12305 ub = lb;
12306 val *= -1;
12307 }
12308
12309 found = TRUE;
12310
12311 frac += (val - SCIPfloor(scip, val)) * ub;
12312
12313 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12314 *
12315 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12316 * x3, x4 set to 1 would be infeasible but feasible after flooring
12317 */
12318 if( SCIPisGT(scip, frac, siderest) )
12319 return SCIP_OKAY;
12320 }
12321 }
12322 assert(v == -1);
12323
12324 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12325
12326 /* round rhs and coefficients to integral values */
12327 if( found )
12328 {
12329 for( v = nvars - 1; v >= 0; --v )
12330 {
12331 val = vals[v];
12332
12333 /* add the whole fractional part */
12334 if( !SCIPisIntegral(scip, val) )
12335 {
12336 lb = SCIPvarGetLbGlobal(vars[v]);
12337
12338 if( SCIPisFeasZero(scip, lb) )
12339 newval = SCIPfloor(scip, val);
12340 else
12341 newval = SCIPceil(scip, val);
12342
12343 if( SCIPisZero(scip, newval) )
12344 {
12345 /* delete old redundant coefficient */
12346 SCIP_CALL( delCoefPos(scip, cons, v) );
12347 ++(*nchgcoefs);
12348 }
12349 else
12350 {
12351 /* replace old with new coefficient */
12352 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12353 ++(*nchgcoefs);
12354 }
12355 }
12356 }
12357 }
12358
12359 /* replace old with new right hand side */
12360 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12361 ++(*nchgsides);
12362 }
12363 }
12364 else
12365 {
12366 if( allcoefintegral )
12367 {
12368 /* replace old with new left hand side */
12369 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12370 ++(*nchgsides);
12371 }
12372 else
12373 {
12374 /* cannot floor left hand side to zero */
12375 if( SCIPisLT(scip, lhs, 1.0) )
12376 return SCIP_OKAY;
12377
12378 siderest = lhs - SCIPfloor(scip, lhs);
12379
12380 /* try to round down all non-integral coefficients */
12381 for( v = nvars - 1; v >= 0; --v )
12382 {
12383 val = vals[v];
12384
12385 /* add up all possible fractional parts */
12386 if( !SCIPisIntegral(scip, val) )
12387 {
12388 lb = SCIPvarGetLbGlobal(vars[v]);
12389 ub = SCIPvarGetUbGlobal(vars[v]);
12390
12391 /* at least one bound need to be at zero */
12392 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12393 return SCIP_OKAY;
12394
12395 /* swap bounds for 'standard' form */
12396 if( !SCIPisFeasZero(scip, lb) )
12397 {
12398 ub = lb;
12399 val *= -1;
12400 }
12401
12402 /* cannot floor to zero */
12403 if( SCIPisLT(scip, val, 1.0) )
12404 return SCIP_OKAY;
12405
12406 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12407 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12408 return SCIP_OKAY;
12409
12410 found = TRUE;
12411
12412 frac += (val - SCIPfloor(scip, val)) * ub;
12413
12414 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12415 * fractional parts of the variables, we cannot tighten the coefficients
12416 *
12417 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12418 * x2-x4 set to 1 would be feasible but not after flooring
12419 */
12420 if( SCIPisGE(scip, frac, 1 + siderest) )
12421 return SCIP_OKAY;
12422 }
12423 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12424 else
12425 return SCIP_OKAY;
12426 }
12427 assert(v == -1);
12428
12429 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12430
12431 /* round lhs and coefficients to integral values */
12432 if( found )
12433 {
12434 for( v = nvars - 1; v >= 0; --v )
12435 {
12436 val = vals[v];
12437
12438 /* add the whole fractional part */
12439 if( !SCIPisIntegral(scip, val) )
12440 {
12441 lb = SCIPvarGetLbGlobal(vars[v]);
12442
12443 if( SCIPisFeasZero(scip, lb) )
12444 newval = SCIPfloor(scip, val);
12445 else
12446 newval = SCIPceil(scip, val);
12447
12448 if( SCIPisZero(scip, newval) )
12449 {
12450 /* delete old redundant coefficient */
12451 SCIP_CALL( delCoefPos(scip, cons, v) );
12452 ++(*nchgcoefs);
12453 }
12454 else
12455 {
12456 /* replace old with new coefficient */
12457 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12458 ++(*nchgcoefs);
12459 }
12460 }
12461 }
12462 }
12463
12464 /* replace old with new left hand side */
12465 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12466 ++(*nchgsides);
12467 }
12468 }
12469
12470 /* normalize constraint */
12471 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12472 assert(vars == consdata->vars);
12473 assert(vals == consdata->vals);
12474
12475 if( *infeasible )
12476 return SCIP_OKAY;
12477
12478 rhs = consdata->rhs;
12479 lhs = consdata->lhs;
12480
12481 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12482 assert(!haslhs || !SCIPisNegative(scip, lhs));
12483
12485
12486 nvars = consdata->nvars;
12487 if( nvars < 2 )
12488 return SCIP_OKAY;
12489
12491#ifndef NDEBUG
12492 /* debug check if all coefficients are really integral */
12493 for( v = nvars - 1; v >= 0; --v )
12494 assert(SCIPisIntegral(scip, vals[v]));
12495#endif
12496 }
12497
12498 /* @todo following can also work on non integral coefficients, need more investigation */
12499 /* only check constraints with integral coefficients on all integral variables */
12500 if( !allcoefintegral )
12501 return SCIP_OKAY;
12502
12503 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12504 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12505 return SCIP_OKAY;
12506
12507 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12508 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12509 return SCIP_OKAY;
12510
12511 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12512 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12513 return SCIP_OKAY;
12514
12515 assert(nvars >= 2);
12516
12517 /* start gcd procedure for all variables */
12518 do
12519 {
12520 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12521 SCIPdebug( oldnchgsides = *nchgsides; )
12522
12523 /* stop if we have two coeffcients which are one in absolute value */
12524 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12525 return SCIP_OKAY;
12526
12527 gcd = -1;
12528
12529 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12530 * because coefficients of non-binary variables might have changed to zero */
12531 if( !onlybin )
12532 {
12533 foundbin = -1;
12534 onlybin = TRUE;
12535
12536 for( v = nvars - 1; v >= 0; --v )
12537 {
12538 assert(!SCIPisZero(scip, vals[v]));
12540
12541 if( SCIPvarIsBinary(vars[v]) )
12542 {
12543 if( foundbin == -1 )
12544 foundbin = v;
12545 continue;
12546 }
12547 else
12548 onlybin = FALSE;
12549
12550 absval = REALABS(vals[v]);
12551 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12552 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12553 */
12555
12556 if( gcd == -1 )
12557 {
12558 gcd = (SCIP_Longint)(absval + feastol);
12559 assert(gcd >= 1);
12560 }
12561 else
12562 {
12563 /* calculate greatest common divisor for all general variables */
12564 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12565 }
12566 if( gcd == 1 )
12567 break;
12568 }
12569 }
12570 else
12571 foundbin = nvars - 1;
12572
12573 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12574 if( gcd == 1 || foundbin == -1)
12575 return SCIP_OKAY;
12576
12577 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12578
12579 candpos = -1;
12580 candpos2 = -1;
12581
12582 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12583 * change the coefficient
12584 */
12585 for( v = foundbin; v >= 0; --v )
12586 {
12587 if( onlybin || SCIPvarIsBinary(vars[v]) )
12588 {
12589 absval = REALABS(vals[v]);
12590 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12591 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12592 */
12594
12595 oldgcd = gcd;
12596
12597 if( gcd == -1 )
12598 {
12599 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12600 assert(gcd >= 1);
12601 }
12602 else
12603 {
12604 /* calculate greatest common divisor for all general and binary variables */
12605 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12606 }
12607
12608 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12609 * can terminate
12610 */
12611 if( gcd == 1 )
12612 {
12613 /* found candidate */
12614 if( candpos == -1 )
12615 {
12616 gcd = oldgcd;
12617 candpos = v;
12618
12619 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12620 * the coefficient change
12621 */
12622 if( onlybin && v == foundbin - 1 )
12624 }
12625 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12626 else
12627 {
12628 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12629 {
12630 assert(candpos2 == nvars - 1);
12631
12632 /* take new candidates */
12633 candpos = candpos2;
12634
12635 /* recalculate gcd from scratch */
12636 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12637 assert(gcd >= 1);
12638
12639 /* calculate greatest common divisor for all general and binary variables */
12640 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12641 if( gcd == 1 )
12642 return SCIP_OKAY;
12643 }
12644 else
12645 /* cannot determine a possible coefficient for reduction */
12646 return SCIP_OKAY;
12647 }
12648 }
12649 }
12650 }
12651 assert(gcd >= 2);
12652
12653 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12654 * further
12655 */
12656 assert(candpos >= 0 && candpos < nvars);
12657
12658 /* all variables and all coefficients are integral, so the side should be too */
12659 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12660
12661 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12662 * @see normalizeCons()
12663 */
12664 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12665 assert(!haslhs || !SCIPisNegative(scip, lhs));
12666
12667 /* determine the remainder of the side and the gcd */
12668 if( hasrhs )
12669 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12670 else
12671 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12672 assert(rest >= 0);
12673 assert(rest < gcd);
12674
12675 /* determine the remainder of the coefficient candidate and the gcd */
12676 if( vals[candpos] < 0 )
12677 {
12678 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12679 assert(restcoef <= -1);
12680 restcoef += gcd;
12681 }
12682 else
12683 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12684 assert(restcoef >= 1);
12685 assert(restcoef < gcd);
12686
12687 if( hasrhs )
12688 {
12689 if( rest > 0 )
12690 {
12691 /* replace old with new right hand side */
12692 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12693 ++(*nchgsides);
12694 }
12695
12696 /* calculate new coefficient */
12697 if( restcoef > rest )
12698 newcoef = vals[candpos] - restcoef + gcd;
12699 else
12700 newcoef = vals[candpos] - restcoef;
12701 }
12702 else
12703 {
12704 if( rest > 0 )
12705 {
12706 /* replace old with new left hand side */
12707 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12708 ++(*nchgsides);
12709 }
12710
12711 /* calculate new coefficient */
12712 if( rest == 0 || restcoef < rest )
12713 newcoef = vals[candpos] - restcoef;
12714 else
12715 newcoef = vals[candpos] - restcoef + gcd;
12716 }
12717 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12718
12719 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));
12720
12721 if( SCIPisZero(scip, newcoef) )
12722 {
12723 /* delete redundant coefficient */
12724 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12725 }
12726 else
12727 {
12728 /* replace old with new coefficient */
12730 }
12731 ++(*nchgcoefs);
12732
12733 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12734 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12735 assert(vars == consdata->vars);
12736 assert(vals == consdata->vals);
12737
12738 if( *infeasible )
12739 return SCIP_OKAY;
12740
12742
12743 rhs = consdata->rhs;
12744 lhs = consdata->lhs;
12745 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12746 assert(!haslhs || !SCIPisNegative(scip, lhs));
12747
12748 nvars = consdata->nvars;
12749
12750 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));
12751 }
12752 while( nvars >= 2 );
12753
12754 return SCIP_OKAY;
12755}
12756
12757
12758/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12759 * cons0 := a * cons0 + b * cons1,
12760 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12761 * for numerical stability, we will only accept integral a and b;
12762 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12763 * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12764 */
12765static
12767 SCIP* scip, /**< SCIP data structure */
12768 SCIP_CONS* cons0, /**< (in)equality to modify */
12769 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12770 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12771 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12772 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12773 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12774 int nvarscommon, /**< number of variables, that appear in both constraints */
12775 int commonidxweight, /**< variable weight sum of common variables */
12776 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12777 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12778 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12779 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12780 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12781 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12782 )
12783{
12786 SCIP_Real a;
12787 SCIP_Real b;
12788 SCIP_Real aggrcoef;
12789 SCIP_Real scalarsum;
12790 SCIP_Real bestscalarsum;
12791 SCIP_Bool betterscalarsum;
12792 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12793 int varweight;
12794 int nvars;
12795 int bestvarweight;
12796 int bestnvars;
12797 int bestv;
12798 int v;
12799 int i;
12800
12801 assert(scip != NULL);
12802 assert(cons0 != NULL);
12803 assert(cons1 != NULL);
12808 assert(nvarscommon >= 1);
12810 assert(nchgcoefs != NULL);
12812
12815
12816 *infeasible = FALSE;
12817
12818 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12819
12820 /* cons0 is an (in)equality */
12822 assert(consdata0 != NULL);
12823 assert(consdata0->nvars >= 1);
12824 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12826
12827 /* cons1 is an equality */
12829 assert(consdata1 != NULL);
12830 assert(consdata1->nvars >= 1);
12831 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12833
12834 *aggregated = FALSE;
12835
12836 /* search for the best common variable such that
12837 * val1[var] * consdata0 - val0[var] * consdata1
12838 * has least weighted number of variables
12839 */
12841 bestnvars = consdata0->nvars;
12842 bestv = -1;
12843 bestscalarsum = 0.0;
12845 for( v = 0; v < nvarscommon; ++v )
12846 {
12847 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12848 a = consdata1->vals[commonidx1[v]];
12849 b = -consdata0->vals[commonidx0[v]];
12850
12851 /* only try aggregation, if coefficients are integral (numerical stability) */
12853 {
12854 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12856 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12857 scalarsum = REALABS(a) + REALABS(b);
12859 for( i = 0; i < nvarscommon
12861 {
12862 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12863 if( !SCIPisZero(scip, aggrcoef) )
12864 {
12866 nvars++;
12867 }
12868 }
12870 {
12871 bestv = v;
12873 bestnvars = nvars;
12875 }
12876 }
12877
12878 /* update commonvarlindependent flag, if still TRUE:
12879 * 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
12880 */
12881 if( commonvarlindependent && v > 0 )
12883 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12884 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12885 }
12886
12887 /* if better aggregation was found, create new constraint and delete old one */
12889 {
12892 SCIP_VAR** newvars;
12893 SCIP_Real* newvals;
12894 SCIP_Real newlhs;
12895 SCIP_Real newrhs;
12896 int newnvars;
12897
12898 if( bestv != -1 )
12899 {
12900 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12901 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12902 {
12903 a = consdata1->vals[commonidx1[bestv]];
12904 b = -consdata0->vals[commonidx0[bestv]];
12905 }
12906 else
12907 {
12908 a = -consdata1->vals[commonidx1[bestv]];
12909 b = consdata0->vals[commonidx0[bestv]];
12910 }
12914 assert(!SCIPisZero(scip, b));
12915 }
12916 else
12917 {
12919 if( consdata1->vals[commonidx1[0]] > 0.0 )
12920 {
12921 a = consdata1->vals[commonidx1[0]];
12922 b = -consdata0->vals[commonidx0[0]];
12923 }
12924 else
12925 {
12926 a = -consdata1->vals[commonidx1[0]];
12927 b = consdata0->vals[commonidx0[0]];
12928 }
12930 assert(!SCIPisZero(scip, b));
12931
12932 /* if a/b is integral, then we can easily choose integer multipliers */
12933 if( SCIPisIntegral(scip, a/b) )
12934 {
12935 if( a/b > 0 )
12936 {
12937 a /= b;
12938 b = 1.0;
12939 }
12940 else
12941 {
12942 a /= -b;
12943 b = -1.0;
12944 }
12945 }
12946
12947 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12949 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12950 }
12951
12952 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12957
12958 /* get temporary memory for creating the new linear constraint */
12961
12962 /* calculate the common coefficients, if we have not recognized linear dependency */
12963 newnvars = 0;
12965 {
12966 for( i = 0; i < nvarscommon; ++i )
12967 {
12968 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12969 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12970
12971 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12972 if( !SCIPisZero(scip, aggrcoef) )
12973 {
12975 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12977 newnvars++;
12978 }
12979 }
12980 }
12981 else
12982 {
12983 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12984#ifndef NDEBUG
12985 for( i = 0; i < nvarscommon; ++i )
12986 {
12987 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12988 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12989
12990 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12992 }
12993#endif
12994 }
12995
12996 /* calculate the coefficients appearing in cons0 but not in cons1 */
12997 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12998 {
12999 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
13000
13001 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
13004 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
13006 newnvars++;
13007 }
13008
13009 /* calculate the coefficients appearing in cons1 but not in cons0 */
13010 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
13011 {
13012 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
13013
13014 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
13017 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
13019 newnvars++;
13020 }
13022
13023 /* calculate the new left and right hand side of the (in)equality */
13026 if( SCIPisInfinity(scip, -consdata0->lhs) )
13028 else
13029 newlhs = a * consdata0->lhs + b * consdata1->lhs;
13030 if( SCIPisInfinity(scip, consdata0->rhs) )
13032 else
13033 newrhs = a * consdata0->rhs + b * consdata1->rhs;
13034
13035 /* create the new linear constraint */
13041
13044
13045 /* copy the upgraded flag from the old cons0 to the new constraint */
13046 newconsdata->upgraded = consdata0->upgraded;
13047
13048 /* normalize the new constraint */
13049 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
13050
13051 if( *infeasible )
13052 goto TERMINATE;
13053
13054 /* check, if we really want to use the new constraint instead of the old one:
13055 * use the new one, if the maximum norm doesn't grow too much
13056 */
13058 {
13059 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
13061
13062 /* update the statistics: we changed all coefficients */
13063 if( !consdata0->upgraded )
13064 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
13065 *aggregated = TRUE;
13066
13067 /* delete the old constraint, and add the new linear constraint to the problem */
13070 }
13071
13072 TERMINATE:
13073 /* release the new constraint */
13075
13076 /* free temporary memory */
13078 SCIPfreeBufferArray(scip, &newvars);
13079 }
13080
13081 return SCIP_OKAY;
13082}
13083
13084/** gets the key of the given element */
13085static
13087{ /*lint --e{715}*/
13088 /* the key is the element itself */
13089 return elem;
13090}
13091
13092/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13093 * coefficients are either equal or negated
13094 */
13095static
13097{
13098 SCIP* scip;
13101 SCIP_Real cons1scale;
13102 SCIP_Real cons2scale;
13103 int i;
13104
13105 assert(key1 != NULL);
13106 assert(key2 != NULL);
13109 assert(consdata1->indexsorted);
13110 assert(consdata2->indexsorted);
13111
13112 scip = (SCIP*)userptr;
13113 assert(scip != NULL);
13114
13115 /* if it is the same constraint we dont need to check anything */
13116 if( key1 == key2 )
13117 return TRUE;
13118
13119 /* checks trivial case */
13120 if( consdata1->nvars != consdata2->nvars )
13121 return FALSE;
13122
13123 /* tests if variables are equal */
13124 for( i = 0; i < consdata1->nvars; ++i )
13125 {
13126 if( consdata1->vars[i] != consdata2->vars[i] )
13127 {
13128 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13129 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13130 return FALSE;
13131 }
13132 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13133 }
13134
13135 /* compute scale before comparing coefficients of constraints */
13136 cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
13137 cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
13138
13139 /* tests if coefficients are equal with the computed scale */
13140 for( i = 0; i < consdata1->nvars; ++i )
13141 {
13142 SCIP_Real val1;
13143 SCIP_Real val2;
13144
13145 val1 = consdata1->vals[i] * cons1scale;
13146 val2 = consdata2->vals[i] * cons2scale;
13147
13148 if( !SCIPisEQ(scip, val1, val2) )
13149 return FALSE;
13150 }
13151
13152 return TRUE;
13153}
13154
13155/** returns the hash value of the key */
13156static
13158{
13159 SCIP_CONSDATA* consdata;
13160 int minidx;
13161 int mididx;
13162 int maxidx;
13163 SCIP_Real scale;
13164#ifndef NDEBUG
13165 SCIP* scip;
13166
13167 scip = (SCIP*)userptr;
13168 assert(scip != NULL);
13169#endif
13170
13171 assert(key != NULL);
13172 consdata = SCIPconsGetData((SCIP_CONS*)key);
13173 assert(consdata != NULL);
13174 assert(consdata->nvars > 0);
13175
13176 assert(consdata->indexsorted);
13177
13178 minidx = SCIPvarGetIndex(consdata->vars[0]);
13179 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13180 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13181 scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
13182
13183 /* using only the variable indices as hash, since the values are compared by epsilon */
13184 return SCIPhashSeven(consdata->nvars, minidx, SCIPrealHashCode(consdata->vals[0] * scale),
13185 mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale),
13186 maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale));
13187}
13188
13189/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13190 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13191 */
13192static
13194 SCIP_CONS* cons /**< linear constraint */
13195 )
13196{
13197 SCIP_CONSDATA* consdata;
13198
13199 assert(cons != NULL);
13200
13201 consdata = SCIPconsGetData(cons);
13202 assert(consdata != NULL);
13203
13204 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13205}
13206
13207/** updates the hashtable such that out of all constraints in the hashtable that are detected
13208 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13209 * and all others are removed from the hashtable and stored in the given array
13210 */
13211static
13213 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13214 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13215 * upon return will contain the constraint that should be kept */
13216 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13217 * these constraints where removed from the hashtable */
13218 int* nparallelconss /**< pointer to return number of parallel constraints */
13219 )
13220{
13222 unsigned int querykey;
13223
13224 *nparallelconss = 0;
13226
13227 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13228 {
13229 unsigned int conskey = getParallelConsKey(parallelcons);
13230
13231 if( conskey < querykey )
13232 {
13233 parallelconss[(*nparallelconss)++] = *querycons;
13235 querykey = conskey;
13236 }
13237 else
13238 {
13239 parallelconss[(*nparallelconss)++] = parallelcons;
13240 }
13241
13242 /* if the constraint that just came out of the hash table is the one that is kept,
13243 * we do not need to look into the hashtable again, since the invariant is that
13244 * in the hashtable only pair-wise non-parallel constraints are contained.
13245 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13246 * could be contained due to non-transitivity of the equality comparison.
13247 * Also we can return immediately, since parallelcons is already contained in the
13248 * hashtable and we do not need to remove and reinsert it.
13249 */
13250 if( *querycons == parallelcons )
13251 return SCIP_OKAY;
13252
13253 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13254 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13255 }
13256
13257 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13258 * comnpares equal to querycons at this point
13259 */
13260#ifndef NDEBUG
13262#else
13263 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13264#endif
13265
13266 return SCIP_OKAY;
13267}
13268
13269/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13270 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13271 */
13272static
13274 SCIP* scip, /**< SCIP data structure */
13275 BMS_BLKMEM* blkmem, /**< block memory */
13276 SCIP_CONS** conss, /**< constraint set */
13277 int nconss, /**< number of constraints in constraint set */
13278 int* firstchange, /**< pointer to store first changed constraint */
13279 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13280 int* ndelconss, /**< pointer to count number of deleted constraints */
13281 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13282 )
13283{
13284 SCIP_HASHTABLE* hashtable;
13286 int nparallelconss;
13287 int hashtablesize;
13288 int c;
13289
13290 assert(scip != NULL);
13291 assert(blkmem != NULL);
13292 assert(conss != NULL);
13294 assert(cutoff != NULL);
13295 assert(ndelconss != NULL);
13296 assert(nchgsides != NULL);
13297
13298 /* create a hash table for the constraint set */
13299 hashtablesize = nconss;
13300 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13302
13304
13305 /* check all constraints in the given set for redundancy */
13306 for( c = 0; c < nconss; ++c )
13307 {
13310
13311 cons0 = conss[c];
13312
13314 continue;
13315
13316 /* do not check for parallel constraints if they should not be upgraded */
13318 continue;
13319
13320 /* check for interuption */
13321 if( c % 1000 == 0 && SCIPisStopped(scip) )
13322 break;
13323
13324 /* sorts the constraint */
13326 assert(consdata0 != NULL);
13328 assert(consdata0->indexsorted);
13329
13330 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13331 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13332 * first variable is positive
13333 * Also inserts cons0 into the hashtable.
13334 */
13336
13337 if( nparallelconss != 0 )
13338 {
13339 SCIP_Real lhs;
13340 SCIP_Real rhs;
13341
13342 int i;
13343
13344 /* cons0 may have been changed in retrieveParallelConstraints() */
13346
13347 lhs = consdata0->lhs;
13348 rhs = consdata0->rhs;
13349
13350 for( i = 0; i < nparallelconss; ++i )
13351 {
13354 SCIP_Real scale;
13355
13358
13359 /* do not delete constraint if it should not be upgraded */
13361 continue;
13362
13365
13366 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13367 * delete old constraints afterwards
13368 */
13370 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13371
13372 assert(consdatadel->indexsorted);
13373 assert(consdata0->vars[0] == consdatadel->vars[0]);
13374
13375 scale = consdata0->vals[0] / consdatadel->vals[0];
13376 assert(scale != 0.0);
13377
13378 /* in debug mode, check that all coefficients are equal with respect to epsilon
13379 * if the constraints are in equilibrium scale
13380 */
13381#ifndef NDEBUG
13382 {
13383 int k;
13384 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13385 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13386
13387 for( k = 0; k < consdata0->nvars; ++k )
13388 {
13389 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13390 }
13391 }
13392#endif
13393
13394 if( scale > 0.0 )
13395 {
13396 /* the coefficients of both constraints are parallel with a positive scale */
13397 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13401
13402 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13403 lhs = MAX(scale * consdatadel->lhs, lhs);
13404
13405 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13406 rhs = MIN(scale * consdatadel->rhs, rhs);
13407 }
13408 else
13409 {
13410 /* the coefficients of both rows are negations */
13411 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13415
13416 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13417 lhs = MAX(scale * consdatadel->rhs, lhs);
13418
13419 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13420 rhs = MIN(scale * consdatadel->lhs, rhs);
13421 }
13422
13423 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13425
13426 /* delete consdel */
13427 assert( ! consdata0->upgraded || consdatadel->upgraded );
13429 if( !consdatadel->upgraded )
13430 (*ndelconss)++;
13431 }
13432
13433 if( SCIPisFeasLT(scip, rhs, lhs) )
13434 {
13435 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13436 *cutoff = TRUE;
13437 break;
13438 }
13439
13440 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13441 if( lhs > rhs )
13442 {
13443 rhs = (lhs + rhs)/2;
13444 lhs = rhs;
13445 }
13446
13447 /* update lhs and rhs of cons0 */
13448 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13449 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13450
13451 /* update the first changed constraint to begin the next aggregation round with */
13452 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13454
13456 }
13457 }
13458#ifdef SCIP_MORE_DEBUG
13459 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13461#endif
13462
13464
13465 /* free hash table */
13466 SCIPhashtableFree(&hashtable);
13467
13468 return SCIP_OKAY;
13469}
13470
13471/** compares constraint with all prior constraints for possible redundancy or aggregation,
13472 * and removes or changes constraint accordingly
13473 */
13474static
13476 SCIP* scip, /**< SCIP data structure */
13477 SCIP_CONS** conss, /**< constraint set */
13478 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13479 int chkind, /**< index of constraint to check against all prior indices upto startind */
13480 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13481 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13482 int* ndelconss, /**< pointer to count number of deleted constraints */
13483 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13484 int* nchgcoefs /**< pointer to count number of changed coefficients */
13485 )
13486{
13489 int* commonidx0;
13490 int* commonidx1;
13491 int* diffidx0minus1;
13492 int* diffidx1minus0;
13493 uint64_t possignature0;
13494 uint64_t negsignature0;
13495 SCIP_Bool cons0changed;
13496 SCIP_Bool cons0isequality;
13498 int c;
13499 SCIP_Real cons0lhs;
13500 SCIP_Real cons0rhs;
13501 SCIP_Bool cons0upgraded;
13502
13503 assert(scip != NULL);
13504 assert(conss != NULL);
13506 assert(cutoff != NULL);
13507 assert(ndelconss != NULL);
13508 assert(nchgsides != NULL);
13509 assert(nchgcoefs != NULL);
13510
13511 /* get the constraint to be checked against all prior constraints */
13512 cons0 = conss[chkind];
13513 assert(cons0 != NULL);
13516
13518 assert(consdata0 != NULL);
13519 assert(consdata0->nvars >= 1);
13521
13522 /* sort the constraint */
13524
13525 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13527 possignature0 = consdata0->possignature;
13528 negsignature0 = consdata0->negsignature;
13529
13530 /* get temporary memory for indices of common variables */
13536
13537 cons0lhs = consdata0->lhs;
13538 cons0rhs = consdata0->rhs;
13539 cons0upgraded = consdata0->upgraded;
13540
13541 /* check constraint against all prior constraints */
13542 cons0changed = consdata0->changed;
13543 consdata0->changed = FALSE;
13544 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13545 {
13548 uint64_t possignature1;
13549 uint64_t negsignature1;
13550 SCIP_Bool cons0dominateslhs;
13551 SCIP_Bool cons1dominateslhs;
13552 SCIP_Bool cons0dominatesrhs;
13553 SCIP_Bool cons1dominatesrhs;
13554 SCIP_Bool cons1isequality;
13555 SCIP_Bool coefsequal;
13556 SCIP_Bool coefsnegated;
13557 SCIP_Bool tryaggregation;
13558 int nvarscommon;
13559 int nvars0minus1;
13560 int nvars1minus0;
13561 int commonidxweight;
13564 int v0;
13565 int v1;
13566
13567 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13568 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13569 assert(cons0upgraded == consdata0->upgraded);
13570
13571 cons1 = conss[c];
13572
13573 /* cons1 has become inactive during presolving of constraint pairs */
13574 if( cons1 == NULL )
13575 continue;
13576
13579
13581 assert(consdata1 != NULL);
13582
13583 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13584 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13585 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13586
13587 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13588 if( !cons0changed && !consdata1->changed )
13589 continue;
13590
13591 /* if both constraints are already upgraded, skip the pair;
13592 * because changes on these constraints cannot be applied to the instance anymore */
13593 if( cons0upgraded && consdata1->upgraded )
13594 continue;
13595
13596 assert(consdata1->nvars >= 1);
13597
13598 /* sort the constraint */
13600
13601 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13603 possignature1 = consdata1->possignature;
13604 negsignature1 = consdata1->negsignature;
13605
13606 /* the signatures give a quick test to check for domination and equality of coefficients */
13610 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13611 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13613 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13614 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13616 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13617 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13619 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13620 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13622 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13625 continue;
13626
13627 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13629 {
13632 }
13633
13634 /* check consdata0 against consdata1:
13635 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13636 * consdata0 dominates consdata1 w.r.t. left hand side
13637 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13638 * consdata0 dominates consdata1 w.r.t. right hand side
13639 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13640 * ranged row (or equality)
13641 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13642 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13643 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13644 * number of continuous and integer variables are preferred:
13645 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13646 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13647 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13648 * to be positive to not switch the sense of the (in)equality cons0
13649 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13650 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13651 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13652 * to be positive to not switch the sense of the (in)equality cons1
13653 */
13654
13655 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13656 nvarscommon = 0;
13657 commonidxweight = 0;
13658 nvars0minus1 = 0;
13660 nvars1minus0 = 0;
13662 v0 = 0;
13663 v1 = 0;
13667 {
13668 SCIP_VAR* var;
13669 SCIP_Real val0;
13670 SCIP_Real val1;
13671 int varcmp;
13672
13673 /* test, if variable appears in only one or in both constraints */
13675 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13676 else if( v0 < consdata0->nvars )
13677 varcmp = -1;
13678 else
13679 varcmp = +1;
13680
13681 switch( varcmp )
13682 {
13683 case -1:
13684 /* variable doesn't appear in consdata1 */
13685 var = consdata0->vars[v0];
13686 val0 = consdata0->vals[v0];
13687 val1 = 0.0;
13688 if( tryaggregation )
13689 {
13691 nvars0minus1++;
13693 }
13694 v0++;
13695 coefsequal = FALSE;
13697 break;
13698
13699 case +1:
13700 /* variable doesn't appear in consdata0 */
13701 var = consdata1->vars[v1];
13702 val0 = 0.0;
13703 val1 = consdata1->vals[v1];
13704 if( tryaggregation )
13705 {
13707 nvars1minus0++;
13709 }
13710 v1++;
13711 coefsequal = FALSE;
13713 break;
13714
13715 case 0:
13716 /* variable appears in both constraints */
13717 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13718 var = consdata0->vars[v0];
13719 val0 = consdata0->vals[v0];
13720 val1 = consdata1->vals[v1];
13721 if( tryaggregation )
13722 {
13725 nvarscommon++;
13727 }
13728 v0++;
13729 v1++;
13732 break;
13733
13734 default:
13735 SCIPerrorMessage("invalid comparison result\n");
13736 SCIPABORT();
13737 var = NULL;
13738 val0 = 0.0;
13739 val1 = 0.0;
13740 }
13741 assert(var != NULL);
13742
13743 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13744 if( SCIPisGT(scip, val0, val1) )
13745 {
13747 {
13750 }
13752 {
13755 }
13756 }
13757 else if( SCIPisLT(scip, val0, val1) )
13758 {
13760 {
13763 }
13765 {
13768 }
13769 }
13770 }
13771
13772 /* check for disaggregated ranged rows */
13773 if( coefsequal || coefsnegated )
13774 {
13777#ifndef NDEBUG
13779#endif
13781 SCIP_Real lhs;
13782 SCIP_Real rhs;
13783 int consinddel;
13784
13785 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13786 * best left and right hand sides; delete the old constraints afterwards
13787 */
13788 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13789 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13792
13793 if( coefsequal )
13794 {
13795 /* the coefficients of both rows are equal */
13796 lhs = MAX(consdata0->lhs, consdata1->lhs);
13797 rhs = MIN(consdata0->rhs, consdata1->rhs);
13798 }
13799 else
13800 {
13801 /* the coefficients of both rows are negations */
13802 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13803 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13804 }
13805 if( SCIPisFeasLT(scip, rhs, lhs) )
13806 {
13807 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13808 *cutoff = TRUE;
13809 break;
13810 }
13811
13812 /* check which constraint has to stay;
13813 * changes applied to an upgraded constraint will not be considered in the instance */
13814 if( consdata0->upgraded )
13815 {
13816 assert(!consdata1->upgraded);
13817 consstay = cons1;
13818#ifndef NDEBUG
13820#endif
13821
13822 consdel = cons0;
13825 }
13826 else
13827 {
13828 consstay = cons0;
13829#ifndef NDEBUG
13831#endif
13832
13833 consdel = cons1;
13835 consinddel = c;
13836 }
13837
13838 /* update the sides of consstay */
13839 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13840 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13841 if( !consdata0->upgraded )
13842 {
13843 assert(consstay == cons0);
13844 cons0lhs = consdata0->lhs;
13845 cons0rhs = consdata0->rhs;
13846 }
13847
13848 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13850
13851 assert( !consdatastay->upgraded );
13852 /* delete consdel */
13854 conss[consinddel] = NULL;
13855 if( !consdatadel->upgraded )
13856 (*ndelconss)++;
13857 continue;
13858 }
13859
13860 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13861 * redundant
13862 */
13864 {
13865 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13866 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13870
13871 /* check for infeasibility */
13872 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13873 {
13874 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13875 *cutoff = TRUE;
13876 break;
13877 }
13878
13879 /* remove redundant left hand side */
13880 if( !SCIPisInfinity(scip, -consdata0->lhs) )
13881 {
13883 cons0lhs = consdata0->lhs;
13885 if( !consdata0->upgraded )
13886 {
13887 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13889
13890 (*nchgsides)++;
13891 }
13892 }
13893 }
13895 {
13896 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13897 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13901
13902 /* check for infeasibility */
13903 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13904 {
13905 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13906 *cutoff = TRUE;
13907 break;
13908 }
13909
13910 /* remove redundant left hand side */
13911 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13912 {
13915 if( !consdata1->upgraded )
13916 {
13917 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13919
13920 (*nchgsides)++;
13921 }
13922 }
13923 }
13925 {
13926 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13927 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13931
13932 /* check for infeasibility */
13933 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13934 {
13935 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13936 *cutoff = TRUE;
13937 break;
13938 }
13939
13940 /* remove redundant right hand side */
13941 if( !SCIPisInfinity(scip, consdata0->rhs) )
13942 {
13944 cons0rhs = consdata0->rhs;
13946 if( !consdata0->upgraded )
13947 {
13948 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13950
13951 (*nchgsides)++;
13952 }
13953 }
13954 }
13956 {
13957 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13958 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13962
13963 /* check for infeasibility */
13964 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13965 {
13966 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13967 *cutoff = TRUE;
13968 break;
13969 }
13970
13971 /* remove redundant right hand side */
13972 if( !SCIPisInfinity(scip, consdata1->rhs) )
13973 {
13976 if( !consdata1->upgraded )
13977 {
13978 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13980
13981 (*nchgsides)++;
13982 }
13983 }
13984 }
13985
13986 /* check for now redundant constraints */
13988 {
13989 /* consdata0 became redundant */
13990 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13992 conss[chkind] = NULL;
13993 if( !consdata0->upgraded )
13994 {
13995 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13997
13998 (*ndelconss)++;
13999 }
14000 continue;
14001 }
14003 {
14004 /* consdata1 became redundant */
14005 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
14007 conss[c] = NULL;
14008 if( !consdata1->upgraded )
14009 {
14010 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14012
14013 (*ndelconss)++;
14014 }
14015 continue;
14016 }
14017
14018 /* check, if we want to aggregate an (in)equality with an equality:
14019 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
14020 */
14021 if( tryaggregation )
14022 {
14023 SCIP_Bool aggregated;
14024
14027
14028 aggregated = FALSE;
14030 {
14031 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
14034 nchgcoefs, &aggregated, cutoff) );
14035
14036 if( *cutoff )
14037 break;
14038
14039 /* update array of active constraints */
14040 if( aggregated )
14041 {
14044 conss[chkind] = NULL;
14045 }
14046 }
14048 {
14049 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
14052 nchgcoefs, &aggregated, cutoff) );
14053
14054 if( *cutoff )
14055 break;
14056
14057 /* update array of active constraints */
14058 if( aggregated )
14059 {
14062 conss[c] = NULL;
14063 }
14064 }
14065 }
14066 }
14067
14068 /* free temporary memory */
14073
14074 return SCIP_OKAY;
14075}
14076
14077/** do stuffing presolving on a single constraint */
14078static
14080 SCIP* scip, /**< SCIP data structure */
14081 SCIP_CONS* cons, /**< linear constraint */
14082 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14083 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14084 * constraints using the cheapest variable? */
14085 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14086 int* nfixedvars, /**< pointer to count the total number of fixed variables */
14087 int* nchgbds /**< pointer to count the total number of tightened bounds */
14088 )
14089{
14090 SCIP_CONSDATA* consdata;
14091 SCIP_Real* ratios;
14092 int* varpos;
14093 SCIP_Bool* swapped;
14094 SCIP_VAR** vars;
14095 SCIP_Real* vals;
14096 SCIP_VAR* var;
14097 SCIP_Real lb;
14098 SCIP_Real ub;
14099 SCIP_Real minactivity;
14100 SCIP_Real maxactivity;
14101 SCIP_Real maxcondactivity;
14102 SCIP_Real mincondactivity;
14103 SCIP_Real rhs;
14104 SCIP_Real val;
14105 SCIP_Real obj;
14106 SCIP_Real factor;
14107 SCIP_Bool minactisrelax;
14108 SCIP_Bool maxactisrelax;
14109 SCIP_Bool isminsettoinfinity;
14110 SCIP_Bool ismaxsettoinfinity;
14111 SCIP_Bool tryfixing;
14112 int nsingletons;
14113 int idx;
14114 int v;
14115 int nvars;
14116
14117 assert(scip != NULL);
14118 assert(cons != NULL);
14119 assert(nfixedvars != NULL);
14120
14121 consdata = SCIPconsGetData(cons);
14122
14123 /* we only want to run for inequalities */
14124 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14125 return SCIP_OKAY;
14126
14127 if( singlevarstuffing )
14128 {
14129 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
14131 }
14132 else
14133 {
14134 minactivity = SCIP_INVALID;
14135 maxactivity = SCIP_INVALID;
14138 }
14139
14140 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14141 * the new maxactivity is minus the old minactivity then
14142 */
14143 if( SCIPisInfinity(scip, consdata->rhs) )
14144 {
14145 rhs = -consdata->lhs;
14146 factor = -1.0;
14147 maxactivity = -minactivity;
14149 }
14150 else
14151 {
14152 assert(SCIPisInfinity(scip, -consdata->lhs));
14153 rhs = consdata->rhs;
14154 factor = 1.0;
14155 }
14156
14157 nvars = consdata->nvars;
14158 vars = consdata->vars;
14159 vals = consdata->vals;
14160
14161 /* check for continuous singletons */
14162 if( singletonstuffing )
14163 {
14164 for( v = 0; v < nvars; ++v )
14165 {
14166 var = vars[v];
14167
14170 break;
14171 }
14172 }
14173 else
14174 /* we don't want to go into the next block */
14175 v = nvars;
14176
14177 /* a singleton was found -> perform singleton variable stuffing */
14178 if( v < nvars )
14179 {
14180 assert(singletonstuffing);
14181
14185
14186 tryfixing = TRUE;
14187 nsingletons = 0;
14188 mincondactivity = 0.0;
14189 maxcondactivity = 0.0;
14190
14191 for( v = 0; v < nvars; ++v )
14192 {
14193 var = vars[v];
14194 lb = SCIPvarGetLbGlobal(var);
14195 ub = SCIPvarGetUbGlobal(var);
14197 val = factor * vals[v];
14198
14199 assert(!SCIPisZero(scip, val));
14200
14201 /* the variable is a singleton and continuous */
14204 {
14205 if( SCIPisNegative(scip, obj) && val > 0 )
14206 {
14207 /* case 1: obj < 0 and coef > 0 */
14208 if( SCIPisInfinity(scip, -lb) )
14209 {
14210 tryfixing = FALSE;
14211 break;
14212 }
14213
14214 maxcondactivity += val * lb;
14215 mincondactivity += val * lb;
14216 swapped[v] = FALSE;
14217 ratios[nsingletons] = obj / val;
14218 varpos[nsingletons] = v;
14219 nsingletons++;
14220 }
14221 else if( SCIPisPositive(scip, obj) && val < 0 )
14222 {
14223 /* case 2: obj > 0 and coef < 0 */
14224 if( SCIPisInfinity(scip, ub) )
14225 {
14226 tryfixing = FALSE;
14227 break;
14228 }
14229 /* multiply column by (-1) to become case 1.
14230 * now bounds are swapped: ub := -lb, lb := -ub
14231 */
14232
14233 maxcondactivity += val * ub;
14234 mincondactivity += val * ub;
14235 swapped[v] = TRUE;
14236 ratios[nsingletons] = obj / val;
14237 varpos[nsingletons] = v;
14238 nsingletons++;
14239 }
14240 else if( val > 0 )
14241 {
14242 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14243 * we only consider the lower bound for the constants
14244 */
14246
14247 if( SCIPisInfinity(scip, -lb) )
14248 {
14249 /* maybe unbounded */
14250 tryfixing = FALSE;
14251 break;
14252 }
14253
14254 maxcondactivity += val * lb;
14255 mincondactivity += val * lb;
14256 }
14257 else
14258 {
14259 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14260 * we only consider the upper bound for the constants
14261 */
14263 assert(val < 0);
14264
14265 if( SCIPisInfinity(scip, ub) )
14266 {
14267 /* maybe unbounded */
14268 tryfixing = FALSE;
14269 break;
14270 }
14271
14272 maxcondactivity += val * ub;
14273 mincondactivity += val * ub;
14274 }
14275 }
14276 else
14277 {
14278 /* consider contribution of discrete variables, non-singleton
14279 * continuous variables and variables with more than one lock
14280 */
14281 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14282 {
14283 tryfixing = FALSE;
14284 break;
14285 }
14286
14287 if( val > 0 )
14288 {
14289 maxcondactivity += val * ub;
14290 mincondactivity += val * lb;
14291 }
14292 else
14293 {
14294 maxcondactivity += val * lb;
14295 mincondactivity += val * ub;
14296 }
14297 }
14298 }
14300 {
14301 SCIP_Real delta;
14302 SCIP_Bool tightened;
14303#ifdef SCIP_DEBUG
14304 int oldnfixedvars = *nfixedvars;
14305 int oldnchgbds = *nchgbds;
14306#endif
14307
14309
14310 /* verify which singleton continuous variables can be fixed */
14311 for( v = 0; v < nsingletons; ++v )
14312 {
14313 idx = varpos[v];
14314 var = vars[idx];
14315 val = factor * vals[idx];
14316 lb = SCIPvarGetLbGlobal(var);
14317 ub = SCIPvarGetUbGlobal(var);
14318
14320 assert((val < 0) == swapped[idx]);
14321 val = REALABS(val);
14322
14323 /* stop fixing if variable bounds are not finite */
14324 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14325 break;
14326
14330
14331 /* calculate the change in the row activities if this variable changes
14332 * its value from its worst to its best bound
14333 */
14334 if( swapped[idx] )
14335 delta = -(lb - ub) * val;
14336 else
14337 delta = (ub - lb) * val;
14338
14339 assert(!SCIPisNegative(scip, delta));
14340
14341 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14342 {
14343 if( swapped[idx] )
14344 {
14345 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14346 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14347 }
14348 else
14349 {
14350 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14351 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14352 }
14353
14354 if( *cutoff )
14355 break;
14356 if( tightened )
14357 {
14358 (*nfixedvars)++;
14359 }
14360 }
14361 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14362 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14363 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14364 * troubles in case of large bounds.
14365 */
14366 else if( SCIPisLE(scip, rhs, mincondactivity) )
14367 {
14368 if( swapped[idx] )
14369 {
14370 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14371 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14372 }
14373 else
14374 {
14375 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14376 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14377 }
14378
14379 if( *cutoff )
14380 break;
14381 if( tightened )
14382 {
14383 (*nfixedvars)++;
14384 }
14385 }
14386
14387 maxcondactivity += delta;
14388 mincondactivity += delta;
14389 }
14390
14391#ifdef SCIP_DEBUG
14392 if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14393 {
14394 SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14395 }
14396#endif
14397 }
14398
14401 SCIPfreeBufferArray(scip, &varpos);
14402 }
14403
14404 /* perform single-variable stuffing:
14405 * for a linear inequality
14406 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14407 * with a_i > 0 and objective coefficients c_i < 0,
14408 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14409 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14410 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14411 * is redundant.
14412 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14413 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14414 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14415 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14416 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14417 * upper bound.
14418 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14419 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14420 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14421 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14422 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14423 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14424 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14425 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14426 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14427 * c_k * ceil((maxactivity - rhs)/val) is still better than
14428 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14429 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14430 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14431 * sign of coefficients in constraint and objective prevent the use of this method.
14432 */
14433 if( singlevarstuffing && !ismaxsettoinfinity )
14434 {
14435 SCIP_Real bestratio = -SCIPinfinity(scip);
14436 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14437 SCIP_Real ratio;
14438 int bestindex = -1;
14439 int bestuplocks = 0;
14440 int bestdownlocks = 1;
14441 int downlocks;
14442 int uplocks;
14443 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14444 SCIPdebug( int oldnchgbds = *nchgbds; )
14445
14446 /* loop over all variables to identify the best and second-best ratio */
14447 for( v = 0; v < nvars; ++v )
14448 {
14449 var = vars[v];
14451 val = factor * vals[v];
14452
14453 assert(!SCIPisZero(scip, val));
14454
14455 ratio = obj / val;
14456
14457 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14458 if( !SCIPisNegative(scip, ratio) )
14459 {
14460 bestindex = -1;
14461 break;
14462 }
14463
14464 if( val > 0 )
14465 {
14468 }
14469 else
14470 {
14473 }
14474
14475 /* better ratio, update best candidate
14476 * @todo use some tolerance
14477 * @todo check size of domain and updated ratio for integer variables already?
14478 */
14479 if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14482 {
14483 /* best index becomes second-best*/
14484 if( bestindex != -1 )
14485 {
14486 /* second-best index must not have more than 1 uplock */
14487 if( bestuplocks > 1 )
14488 {
14489 bestindex = -1;
14490 break;
14491 }
14492 else
14493 {
14495 }
14496 }
14497 bestdownlocks = downlocks;
14498 bestuplocks = uplocks;
14499 bestratio = ratio;
14500 bestindex = v;
14501
14502 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14503 * if it is not the best, it has too many uplocks -> not applicable
14504 */
14505 if( bestdownlocks > 0 && bestuplocks > 1 )
14506 {
14507 bestindex = -1;
14508 break;
14509 }
14510 }
14511 else
14512 {
14513 /* non-best index must not have more than 1 uplock */
14514 if( uplocks > 1 )
14515 {
14516 bestindex = -1;
14517 break;
14518 }
14519 /* update second-best ratio */
14520 if( ratio > secondbestratio )
14521 {
14522 secondbestratio = ratio;
14523 }
14524 }
14525 }
14526
14527 /* check if we can apply single variable stuffing */
14528 if( bestindex != -1 && bestdownlocks == 0 )
14529 {
14530 SCIP_Bool tightened = FALSE;
14531 SCIP_Real bounddelta;
14532
14533 var = vars[bestindex];
14535 val = factor * vals[bestindex];
14536 lb = SCIPvarGetLbGlobal(var);
14537 ub = SCIPvarGetUbGlobal(var);
14538 tryfixing = TRUE;
14539
14540 if( val < 0 )
14541 {
14543
14544 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14545 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14546 {
14547 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14548 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14550
14552
14553 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14555 }
14556 else
14557 bounddelta = (maxactivity - rhs)/-val;
14558
14559 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14560
14561 if( tryfixing )
14562 {
14564
14565 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14566 {
14567 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14568 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14569 }
14570 else
14571 {
14572 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14573 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14574 }
14575 }
14576 }
14577 else
14578 {
14580
14581 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14582 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14583 {
14584 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14585 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14587
14589
14590 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14592 }
14593 else
14594 bounddelta = (maxactivity - rhs)/val;
14595
14596 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14597
14598 if( tryfixing )
14599 {
14601
14602 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14603 {
14604 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14605 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14606 }
14607 else
14608 {
14609 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14610 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14611 }
14612 }
14613 }
14614
14615 if( *cutoff )
14616 return SCIP_OKAY;
14617 if( tightened )
14618 {
14620 ++(*nfixedvars);
14621 else
14622 ++(*nchgbds);
14623
14624 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14625 for( v = 0; v < nvars; ++v )
14626 {
14627 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14631 SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14632 }
14633 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14634
14635 for( v = 0; v < nvars; ++v )
14636 {
14637 if( v == bestindex )
14638 continue;
14639
14640 if( factor * vals[v] < 0 )
14641 {
14643 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14645 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14646 }
14647 else
14648 {
14650 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14652 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14653 }
14654
14655 if( *cutoff )
14656 return SCIP_OKAY;
14657 if( tightened )
14658 ++(*nfixedvars);
14659 }
14660 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14661 }
14662 }
14663 }
14664
14665 return SCIP_OKAY;
14666}
14667
14668/** applies full dual presolving on variables that only appear in linear constraints */
14669static
14671 SCIP* scip, /**< SCIP data structure */
14672 SCIP_CONS** conss, /**< constraint set */
14673 int nconss, /**< number of constraints */
14674 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14675 int* nchgbds /**< pointer to count the number of bound changes */
14676 )
14677{
14678 SCIP_Real* redlb;
14679 SCIP_Real* redub;
14680 int* nlocksdown;
14681 int* nlocksup;
14682 SCIP_Bool* isimplint;
14683 SCIP_VAR** origvars;
14684 SCIP_VAR** vars;
14686 int nvars;
14687 int nbinvars;
14688 int nintvars;
14689 int ncontvars;
14690 int v;
14691 int c;
14692
14693 /* we calculate redundancy bounds with the following meaning:
14694 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14695 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14696 * then:
14697 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14698 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14699 */
14700
14701 /* Additionally, we detect continuous variables that are implicitly integral.
14702 * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14703 * and all constraints (including the bounds as trivial constraints) in which:
14704 * c_j > 0: the variable is down-locked,
14705 * c_j < 0: the variable is up-locked,
14706 * c_j = 0: the variable appears
14707 * have, apart from j, only integer variables with integral coefficients and integral sides.
14708 * This is because then, the value of the variable is either determined by one of its bounds or
14709 * by one of these constraints, and in all cases, the value of the variable is integral.
14710 */
14711
14712 assert(scip != NULL);
14713 assert(nconss == 0 || conss != NULL);
14714 assert(nchgbds != NULL);
14716
14717 /* get active variables */
14719 origvars = SCIPgetVars(scip);
14720
14721 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14723 if( nbinvars == nvars )
14724 return SCIP_OKAY;
14725
14726 /* get number of continuous variables */
14727 ncontvars = SCIPgetNContVars(scip);
14728 nintvars = nvars - ncontvars;
14729
14730 /* copy the variable array since this array might change during the curse of this algorithm */
14731 nvars = nvars - nbinvars;
14733
14734 /* allocate temporary memory */
14737 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14738 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14741
14742 /* initialize redundancy bounds */
14743 for( v = 0; v < nvars; ++v )
14744 {
14746 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14747 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14748 }
14749 BMSclearMemoryArray(nlocksdown, nvars);
14750 BMSclearMemoryArray(nlocksup, nvars);
14751
14752 /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14753 * We better not use SCIPisFeasIntegral() in these checks.
14754 */
14755 for( v = 0; v < ncontvars; v++ )
14756 {
14757 SCIP_VAR* var;
14758 SCIP_Real obj;
14759 SCIP_Real lb;
14760 SCIP_Real ub;
14761
14762 var = vars[v + nintvars - nbinvars];
14763 lb = SCIPvarGetLbGlobal(var);
14764 ub = SCIPvarGetUbGlobal(var);
14765
14767 if( SCIPisZero(scip, obj) )
14768 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14769 else
14770 {
14771 if( SCIPisPositive(scip, obj) )
14772 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14773 else
14774 {
14776 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14777 }
14778 }
14779 }
14780
14781 /* scan all constraints */
14782 for( c = 0; c < nconss; ++c )
14783 {
14784 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14785 * part of checked disjunctions)
14786 */
14787 if( SCIPconsIsLocked(conss[c]) )
14788 {
14789 SCIP_CONSDATA* consdata;
14790 SCIP_Bool lhsexists;
14791 SCIP_Bool rhsexists;
14792 SCIP_Bool hasimpliedpotential;
14793 SCIP_Bool integralcoefs;
14794 int nlockspos;
14795 int contvarpos;
14796 int nconscontvars;
14797 int i;
14798
14799 consdata = SCIPconsGetData(conss[c]);
14800 assert(consdata != NULL);
14801
14802 /* get number of times the constraint was locked */
14803 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14804
14805 /* we do not want to include constraints with locked negation (this would be too weird) */
14806 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14807 {
14808 /* mark all continuous variables as not being implicit integral */
14809 for( i = 0; i < consdata->nvars; ++i )
14810 {
14811 SCIP_VAR* var;
14812
14813 var = consdata->vars[i];
14815 {
14816 int contv;
14818 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14820 }
14821 }
14822 continue;
14823 }
14824
14825 /* check for existing sides */
14826 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14827 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14828
14829 /* count locks and update redundancy bounds */
14830 contvarpos = -1;
14831 nconscontvars = 0;
14834
14835 for( i = 0; i < consdata->nvars; ++i )
14836 {
14837 SCIP_VAR* var;
14838 SCIP_Real val;
14839 SCIP_Real minresactivity;
14840 SCIP_Real maxresactivity;
14841 SCIP_Real newredlb;
14842 SCIP_Real newredub;
14843 SCIP_Bool minisrelax;
14844 SCIP_Bool maxisrelax;
14845 SCIP_Bool isminsettoinfinity;
14846 SCIP_Bool ismaxsettoinfinity;
14847 int arrayindex;
14848
14849 var = consdata->vars[i];
14850 val = consdata->vals[i];
14851
14852 /* check if still all integer variables have integral coefficients */
14853 if( SCIPvarIsIntegral(var) )
14855
14856 /* we do not need to process binary variables */
14857 if( SCIPvarIsBinary(var) )
14858 continue;
14859
14860 if( SCIPconsIsModifiable(conss[c]) )
14861 {
14866 }
14867 else
14868 {
14869 /* calculate residual activity bounds if variable would be fixed to zero */
14872
14873 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14874 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14875 * This is needed, because we do not want to rely on relaxed finite resactivities.
14876 */
14878
14879 /* check minresactivity for reliability */
14880 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14882
14883 /* check maxresactivity for reliability */
14884 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14886 }
14887
14889
14890 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14891
14894 if( val > 0.0 )
14895 {
14896 if( lhsexists )
14897 {
14898 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14899 nlocksdown[arrayindex] += nlockspos;
14900 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14901 }
14902 if( rhsexists )
14903 {
14904 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14905 nlocksup[arrayindex] += nlockspos;
14906 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14907 }
14908 }
14909 else
14910 {
14911 if( lhsexists )
14912 {
14913 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14914 nlocksup[arrayindex] += nlockspos;
14915 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14916 }
14917 if( rhsexists )
14918 {
14919 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14920 nlocksdown[arrayindex] += nlockspos;
14921 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14922 }
14923 }
14924
14925 /* if the variable is integer, we have to round the value to the next integral value */
14926 if( SCIPvarIsIntegral(var) )
14927 {
14930 if( !SCIPisInfinity(scip, -newredub) )
14932 }
14933
14934 /* update redundancy bounds */
14937
14938 /* collect the continuous variables of the constraint */
14940 {
14941 int contv;
14942
14943 assert(nconscontvars < ncontvars);
14944 contvarpos = i;
14946 nconscontvars++;
14947
14949 assert(0 <= contv && contv < ncontvars);
14951 }
14952 }
14953
14954 /* update implicit integer status of continuous variables */
14956 {
14957 if( nconscontvars > 1 || !integralcoefs )
14958 {
14959 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14960 * none of the continuous variables is implicit integer
14961 */
14962 for( i = 0; i < nconscontvars; i++ )
14963 {
14964 int contv;
14966 assert(0 <= contv && contv < ncontvars);
14968 }
14969 }
14970 else
14971 {
14972 SCIP_VAR* var;
14973 SCIP_Real val;
14974 SCIP_Real absval;
14975 int contv;
14976
14977 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14978 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14979 * side(s) of the constraint is integral
14980 */
14981 assert(nconscontvars == 1);
14983 var = consdata->vars[contvarpos];
14984 val = consdata->vals[contvarpos];
14986 assert(0 <= contv && contv < ncontvars);
14988
14989 absval = REALABS(val);
14990 if( !SCIPisEQ(scip, absval, 1.0) )
14992 else
14993 {
14994 SCIP_Real obj;
14995
14997 if( obj * val >= 0.0 && lhsexists )
14998 {
14999 /* the variable may be blocked by the constraint's left hand side */
15000 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
15001 }
15002 if( obj * val <= 0.0 && rhsexists )
15003 {
15004 /* the variable may be blocked by the constraint's left hand side */
15005 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
15006 }
15007 }
15008 }
15009 }
15010 }
15011 }
15012
15013 /* check if any bounds can be tightened due to optimality */
15014 for( v = 0; v < nvars; ++v )
15015 {
15016 SCIP_VAR* var;
15017 SCIP_Real obj;
15018 SCIP_Bool infeasible;
15019 SCIP_Bool tightened;
15020
15024
15025 var = vars[v];
15027 if( !SCIPisPositive(scip, -obj) )
15028 {
15029 /* making the variable as small as possible does not increase the objective:
15030 * check if all down locks of the variables are due to linear constraints;
15031 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
15032 * constraints redundant is huge, we better do nothing for numerical reasons
15033 */
15036 && !SCIPisHugeValue(scip, -redlb[v])
15037 && redlb[v] < SCIPvarGetUbGlobal(var) )
15038 {
15039 SCIP_Real ub;
15040
15041 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
15042 * -> tighten upper bound to x_v <= redlb[v]
15043 */
15044 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
15046 redlb[v]);
15047 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
15048 assert(!infeasible);
15049
15050 ub = SCIPvarGetUbGlobal(var);
15051 redub[v] = MIN(redub[v], ub);
15052 if( tightened )
15053 (*nchgbds)++;
15054 }
15055 }
15056 if( !SCIPisPositive(scip, obj) )
15057 {
15058 /* making the variable as large as possible does not increase the objective:
15059 * check if all up locks of the variables are due to linear constraints;
15060 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
15061 * constraints redundant is huge, we better do nothing for numerical reasons
15062 */
15065 && !SCIPisHugeValue(scip, redub[v])
15066 && redub[v] > SCIPvarGetLbGlobal(var) )
15067 {
15068 SCIP_Real lb;
15069
15070 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
15071 * -> tighten lower bound to x_v >= redub[v]
15072 */
15073 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
15075 redub[v]);
15076 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15077 assert(!infeasible);
15078
15079 lb = SCIPvarGetLbGlobal(var);
15080 redlb[v] = MAX(redlb[v], lb);
15081 if( tightened )
15082 (*nchgbds)++;
15083 }
15084 }
15085 }
15086
15087 /* upgrade continuous variables to implicit integers */
15088 for( v = nintvars - nbinvars; v < nvars; ++v )
15089 {
15090 SCIP_VAR* var;
15091 SCIP_Bool infeasible;
15092
15093 var = vars[v];
15094 assert(var != NULL);
15095
15099 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15100
15101 /* we can only conclude implicit integrality if the variable appears in no other constraint */
15102 if( isimplint[v - nintvars + nbinvars]
15104 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15105 {
15106 /* since we locally copied the variable array we can change the variable type immediately */
15108
15109 if( infeasible )
15110 {
15111 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15112 *cutoff = TRUE;
15113
15114 break;
15115 }
15116
15117 SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15119 }
15120 }
15121
15122 /* free temporary memory */
15125 SCIPfreeBufferArray(scip, &nlocksup);
15126 SCIPfreeBufferArray(scip, &nlocksdown);
15129
15131
15132 return SCIP_OKAY;
15133}
15134
15135/** helper function to enforce constraints */
15136static
15138 SCIP* scip, /**< SCIP data structure */
15139 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15140 SCIP_CONS** conss, /**< constraints to process */
15141 int nconss, /**< number of constraints */
15142 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15143 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15144 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15145 )
15146{
15147 SCIP_CONSHDLRDATA* conshdlrdata;
15148 SCIP_Bool checkrelmaxabs;
15149 SCIP_Bool violated;
15150 SCIP_Bool cutoff = FALSE;
15151 int c;
15152
15153 assert(scip != NULL);
15154 assert(conshdlr != NULL);
15156 assert(result != NULL);
15157
15158 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15159 assert(conshdlrdata != NULL);
15160
15161 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15162
15163 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15164
15165 /* check for violated constraints
15166 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15167 */
15169
15170 /* check all useful linear constraints for feasibility */
15171 for( c = 0; c < nusefulconss; ++c )
15172 {
15173 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15174
15175 if( violated )
15176 {
15177 /* insert LP row as cut */
15178 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15179 if ( cutoff )
15181 else
15183 }
15184 }
15185
15186 /* check all obsolete linear constraints for feasibility */
15187 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15188 {
15189 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15190
15191 if( violated )
15192 {
15193 /* insert LP row as cut */
15194 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15195 if ( cutoff )
15197 else
15199 }
15200 }
15201
15202 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15203
15204 return SCIP_OKAY;
15205}
15206
15207/** adds symmetry information of constraint to a symmetry detection graph */
15208static
15210 SCIP* scip, /**< SCIP pointer */
15211 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15212 SCIP_CONS* cons, /**< constraint */
15213 SYM_GRAPH* graph, /**< symmetry detection graph */
15214 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15215 )
15216{
15217 SCIP_CONSDATA* consdata;
15218 SCIP_VAR** vars;
15219 SCIP_Real* vals;
15220 SCIP_Real constant = 0.0;
15221 SCIP_Real lhs;
15222 SCIP_Real rhs;
15223 int nlocvars;
15224 int nvars;
15225 int i;
15226
15227 assert(scip != NULL);
15228 assert(cons != NULL);
15229 assert(graph != NULL);
15230 assert(success != NULL);
15231
15232 consdata = SCIPconsGetData(cons);
15233 assert(consdata != NULL);
15234
15235 /* get active variables of the constraint */
15237 nlocvars = consdata->nvars;
15238
15241
15242 for( i = 0; i < nlocvars; ++i )
15243 {
15244 vars[i] = consdata->vars[i];
15245 vals[i] = consdata->vals[i];
15246 }
15247
15248 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15249 lhs = consdata->lhs - constant;
15250 rhs = consdata->rhs - constant;
15251
15252 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15253 * of the same constraint are rated as equal
15254 */
15255 if ( SCIPisInfinity(scip, rhs) )
15256 {
15257 SCIP_Real tmp;
15258 assert(!SCIPisInfinity(scip, -lhs));
15259
15260 for( i = 0; i < nlocvars; ++i )
15261 vals[i] *= -1;
15262 tmp = rhs;
15263 rhs = -lhs;
15264 lhs = -tmp;
15265 }
15266
15268 cons, lhs, rhs, success) );
15269
15270 SCIPfreeBufferArray(scip, &vals);
15272
15273 return SCIP_OKAY;
15274}
15275
15276/*
15277 * Callback methods of constraint handler
15278 */
15279
15280/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15281static
15283{ /*lint --e{715}*/
15284 assert(scip != NULL);
15285 assert(conshdlr != NULL);
15287
15288 /* call inclusion method of constraint handler */
15290
15291 *valid = TRUE;
15292
15293 return SCIP_OKAY;
15294}
15295
15296/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15297static
15299{ /*lint --e{715}*/
15300 SCIP_CONSHDLRDATA* conshdlrdata;
15301
15302 assert(scip != NULL);
15303 assert(conshdlr != NULL);
15305
15306 /* free constraint handler data */
15307 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15308 assert(conshdlrdata != NULL);
15309
15310 conshdlrdataFree(scip, &conshdlrdata);
15311
15312 SCIPconshdlrSetData(conshdlr, NULL);
15313
15314 return SCIP_OKAY;
15315}
15316
15317
15318/** initialization method of constraint handler (called after problem was transformed) */
15319static
15321{
15322 SCIP_CONSHDLRDATA* conshdlrdata;
15323 int c;
15324
15325 assert(scip != NULL);
15326
15327 /* check for event handler */
15328 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15329 assert(conshdlrdata != NULL);
15330 assert(conshdlrdata->eventhdlr != NULL);
15331 assert(nconss == 0 || conss != NULL);
15332
15333 conshdlrdata->naddconss = 0;
15334
15335 /* catch events for the constraints */
15336 for( c = 0; c < nconss; ++c )
15337 {
15338 /* catch all events */
15339 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15340 }
15341
15342 return SCIP_OKAY;
15343}
15344
15345
15346/** deinitialization method of constraint handler (called before transformed problem is freed) */
15347static
15349{
15350 SCIP_CONSHDLRDATA* conshdlrdata;
15351 int c;
15352
15353 assert(scip != NULL);
15354
15355 /* check for event handler */
15356 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15357 assert(conshdlrdata != NULL);
15358 assert(conshdlrdata->eventhdlr != NULL);
15359
15360 /* drop events for the constraints */
15361 for( c = nconss - 1; c >= 0; --c )
15362 {
15363 SCIP_CONSDATA* consdata;
15364
15365 consdata = SCIPconsGetData(conss[c]);
15366 assert(consdata != NULL);
15367
15368 if( consdata->eventdata != NULL )
15369 {
15370 /* drop all events */
15371 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15372 assert(consdata->eventdata == NULL);
15373 }
15374 }
15375
15376 return SCIP_OKAY;
15377}
15378
15379/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15380static
15381SCIP_Bool isRangedRow(
15382 SCIP* scip, /**< SCIP data structure */
15383 SCIP_Real lhs, /**< left hand side */
15384 SCIP_Real rhs /**< right hand side */
15385 )
15386{
15387 assert(scip != NULL);
15388
15389 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15390}
15391
15392/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15393static
15395 SCIP* scip, /**< SCIP data structure */
15396 SCIP_Real x /**< value */
15397 )
15398{
15399 assert(scip != NULL);
15400
15401 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15402}
15403
15404/** performs linear constraint type classification as used for MIPLIB
15405 *
15406 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15407 *
15408 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15409 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15410 * Similarly, if specialized constraints were created through the API, these are currently not present.
15411 */
15413 SCIP* scip, /**< SCIP data structure */
15414 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15415 )
15416{
15417 int c;
15418 SCIP_CONSHDLR* conshdlr;
15419 SCIP_CONS** conss;
15420 int nconss;
15421
15422 assert(scip != NULL);
15424 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15425 assert(conshdlr != NULL);
15426
15428 {
15429 conss = SCIPgetConss(scip);
15430 nconss = SCIPgetNConss(scip);
15431 }
15432 else
15433 {
15434 conss = SCIPconshdlrGetConss(conshdlr);
15435 nconss = SCIPconshdlrGetNConss(conshdlr);
15436 }
15437
15438 /* reset linear constraint type classification */
15440
15441 /* loop through all constraints */
15442 for( c = 0; c < nconss; c++ )
15443 {
15444 SCIP_CONS* cons;
15445 SCIP_CONSDATA* consdata;
15446 SCIP_Real lhs;
15447 SCIP_Real rhs;
15448 int i;
15449
15450 /* get constraint */
15451 cons = conss[c];
15452 assert(cons != NULL);
15453
15454 /* skip constraints that are not handled by the constraint handler */
15455 if( SCIPconsGetHdlr(cons) != conshdlr )
15456 continue;
15457
15458 /* get constraint data */
15459 consdata = SCIPconsGetData(cons);
15460 assert(consdata != NULL);
15461 rhs = consdata->rhs;
15462 lhs = consdata->lhs;
15463
15464 /* merge multiples and delete variables with zero coefficient */
15465 SCIP_CALL( mergeMultiples(scip, cons) );
15466 for( i = 0; i < consdata->nvars; i++ )
15467 {
15468 assert(!SCIPisZero(scip, consdata->vals[i]));
15469 }
15470
15471 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15472 if( consdata->nvars == 0 )
15473 {
15474 SCIPdebugMsg(scip, "classified as EMPTY: ");
15477
15478 continue;
15479 }
15480
15481 /* is constraint of type SCIP_CONSTYPE_FREE? */
15482 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15483 {
15484 SCIPdebugMsg(scip, "classified as FREE: ");
15487
15488 continue;
15489 }
15490
15491 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15492 if( consdata->nvars == 1 )
15493 {
15494 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15497
15498 continue;
15499 }
15500
15501 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15502 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15503 {
15504 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15507
15508 continue;
15509 }
15510
15511 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15512 if( consdata->nvars == 2 )
15513 {
15514 SCIP_LINCONSTYPE constype;
15515
15516 /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15517 if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15518 && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15519 {
15520 constype = SCIP_LINCONSTYPE_PRECEDENCE;
15521 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15522 }
15523 else
15524 {
15525 constype = SCIP_LINCONSTYPE_VARBOUND;
15526 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15527 }
15529
15530 SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15531
15532 continue;
15533 }
15534
15535 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15536 {
15537 SCIP_Real scale;
15538 SCIP_Real b;
15539 SCIP_Bool unmatched;
15540 int nnegbinvars;
15541
15542 unmatched = FALSE;
15543 nnegbinvars = 0;
15544
15545 scale = REALABS(consdata->vals[0]);
15546
15547 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15548 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15549 {
15551 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15552 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15553 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15554
15555 if( consdata->vals[i] < 0.0 )
15556 nnegbinvars++;
15557 }
15558
15559 if( !unmatched )
15560 {
15561 if( SCIPisEQ(scip, lhs, rhs) )
15562 {
15563 b = rhs/scale + nnegbinvars;
15564 if( SCIPisEQ(scip, 1.0, b) )
15565 {
15566 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15569
15570 continue;
15571 }
15572 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15573 {
15574 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15577
15578 continue;
15579 }
15580 }
15581
15582 /* compute right hand side divided by scale */
15583 if( !SCIPisInfinity(scip, rhs) )
15584 b = rhs/scale + nnegbinvars;
15585 else
15586 b = SCIPinfinity(scip);
15587
15588 if( SCIPisEQ(scip, 1.0, b) )
15589 {
15590 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15593
15594 /* relax right hand side to prevent further classifications */
15595 rhs = SCIPinfinity(scip);
15596 }
15597 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15598 {
15599 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15601
15603
15604 /* relax right hand side to prevent further classifications */
15605 rhs = SCIPinfinity(scip);
15606 }
15607
15608 if( !SCIPisInfinity(scip, lhs) )
15609 b = lhs/scale + nnegbinvars;
15610 else
15611 b = SCIPinfinity(scip);
15612
15613 if( SCIPisEQ(scip, 1.0, b) )
15614 {
15615 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15618
15619 /* relax left hand side to prevent further classifications */
15620 lhs = -SCIPinfinity(scip);
15621 }
15622
15623 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15624 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15625 continue;
15626 }
15627 }
15628
15629 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15630 /* @todo If coefficients or rhs are not integral, we currently do not check
15631 * if the constraint could be scaled (finitely), such that they are.
15632 */
15633 {
15634 SCIP_Real b;
15635 SCIP_Bool unmatched;
15636
15637 b = rhs;
15638 unmatched = FALSE;
15639 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15640 {
15642 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15643 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15644 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15645
15646 if( SCIPisNegative(scip, consdata->vals[i]) )
15647 b -= consdata->vals[i];
15648 }
15650
15651 if( !unmatched )
15652 {
15653 if( SCIPisEQ(scip, lhs, rhs) )
15654 {
15655 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15657
15659
15660 continue;
15661 }
15662 else
15663 {
15664 SCIP_Bool matched;
15665
15666 matched = FALSE;
15667 for( i = 0; i < consdata->nvars && !matched; i++ )
15668 {
15669 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15670 }
15671
15672 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15675 }
15676
15677 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15678 if( SCIPisInfinity(scip, -lhs) )
15679 continue;
15680 else
15681 rhs = SCIPinfinity(scip);
15682 }
15683 }
15684
15685 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15686 {
15687 SCIP_Real b;
15688 SCIP_Bool unmatched;
15689
15690 unmatched = FALSE;
15691
15692 b = rhs;
15694
15695 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15696 {
15699 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15700 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15701 }
15702
15703 if( !unmatched )
15704 {
15705 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15708
15709 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15710 if( SCIPisInfinity(scip, -lhs) )
15711 continue;
15712 else
15713 rhs = SCIPinfinity(scip);
15714 }
15715 }
15716
15717 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15718 {
15719 SCIP_Bool unmatched;
15720
15721 unmatched = FALSE;
15722 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15723 {
15724 if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15725 && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15726 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15727 unmatched = TRUE;
15728 }
15729
15730 if( !unmatched )
15731 {
15732 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15735
15736 continue;
15737 }
15738 }
15739
15740 /* no special structure detected */
15741 SCIPdebugMsg(scip, "classified as GENERAL: ");
15744 }
15745
15746 return SCIP_OKAY;
15747}
15748
15749
15750/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15751static
15753{ /*lint --e{715}*/
15754 int c;
15755#ifdef SCIP_STATISTIC
15756 SCIP_CONSHDLRDATA* conshdlrdata;
15757 int ngoodconss;
15758 int nallconss;
15759#endif
15760
15761 /* delete all linear constraints that were upgraded to a more specific constraint type;
15762 * make sure, only active variables remain in the remaining constraints
15763 */
15764 assert(scip != NULL);
15765
15766#ifdef SCIP_STATISTIC
15767 /* count number of well behaved linear constraints */
15768 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15769 assert(conshdlrdata != NULL);
15770
15771 ngoodconss = 0;
15772 nallconss = 0;
15773
15774 for( c = 0; c < nconss; ++c )
15775 {
15776 SCIP_CONSDATA* consdata;
15777
15778 if( SCIPconsIsDeleted(conss[c]) )
15779 continue;
15780
15781 consdata = SCIPconsGetData(conss[c]);
15782 assert(consdata != NULL);
15783
15784 if( consdata->upgraded )
15785 continue;
15786
15787 nallconss++;
15788
15790
15791 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15792 ngoodconss++;
15793 }
15794 if( nallconss )
15795 {
15796 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15797 }
15798#endif
15799
15800 for( c = 0; c < nconss; ++c )
15801 {
15802 SCIP_CONSDATA* consdata;
15803
15804 if( SCIPconsIsDeleted(conss[c]) )
15805 continue;
15806
15807 consdata = SCIPconsGetData(conss[c]);
15808 assert(consdata != NULL);
15809
15810 if( consdata->upgraded )
15811 {
15812 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15813 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15814 */
15815 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15816 }
15817 else
15818 {
15819 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15820 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15821 }
15822 }
15823
15824 return SCIP_OKAY;
15825}
15826
15827/** solving process initialization method of constraint handler */
15828static
15830{ /*lint --e{715}*/
15831 /* add nlrow representation to NLP, if NLP had been constructed */
15833 {
15834 int c;
15835 for( c = 0; c < nconss; ++c )
15836 {
15837 SCIP_CALL( addNlrow(scip, conss[c]) );
15838 }
15839 }
15840
15841 return SCIP_OKAY;
15842}
15843
15844/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15845static
15847{ /*lint --e{715}*/
15848 int c;
15849
15850 assert(scip != NULL);
15851
15852 /* release the rows and nlrows of all constraints */
15853 for( c = 0; c < nconss; ++c )
15854 {
15855 SCIP_CONSDATA* consdata;
15856
15857 consdata = SCIPconsGetData(conss[c]);
15858 assert(consdata != NULL);
15859
15860 if( consdata->row != NULL )
15861 {
15862 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15863 }
15864
15865 if( consdata->nlrow != NULL )
15866 {
15867 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15868 }
15869 }
15870
15871 /* if this is a restart, convert cutpool rows into linear constraints */
15872 if( restart )
15873 {
15874 int ncutsadded;
15875
15876 ncutsadded = 0;
15877
15878 /* create out of all active cuts in cutpool linear constraints */
15879 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15880
15881 if( ncutsadded > 0 )
15882 {
15884 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15885 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15886 * line correctly
15887 */
15889 }
15890 }
15891
15892 return SCIP_OKAY;
15893}
15894
15895
15896/** constraint activation notification method of constraint handler */
15897static
15899{ /*lint --e{715}*/
15900 assert(cons != NULL);
15901
15903 {
15904 SCIP_CALL( addNlrow(scip, cons) );
15905 }
15906
15907 return SCIP_OKAY;
15908}
15909
15910/** constraint deactivation notification method of constraint handler */
15911static
15913{ /*lint --e{715}*/
15914 SCIP_CONSDATA* consdata;
15915
15916 assert(scip != NULL);
15917 assert(conshdlr != NULL);
15919 assert(cons != NULL );
15920
15921 /* get constraint data */
15922 consdata = SCIPconsGetData(cons);
15923 assert(consdata != NULL);
15924
15925 if( SCIPconsIsDeleted(cons) )
15926 {
15927 SCIP_CONSHDLRDATA* conshdlrdata;
15928
15929 /* check for event handler */
15930 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15931 assert(conshdlrdata != NULL);
15932 assert(conshdlrdata->eventhdlr != NULL);
15933
15934 /* free event data */
15935 if( consdata->eventdata != NULL )
15936 {
15937 /* drop bound change events of variables */
15938 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15939 }
15940 assert(consdata->eventdata == NULL);
15941 }
15942
15943 /* remove row from NLP, if still in solving
15944 * if we are in exitsolve, the whole NLP will be freed anyway
15945 */
15946 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15947 {
15948 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15949 }
15950
15951 return SCIP_OKAY;
15952}
15953
15954
15955/** frees specific constraint data */
15956static
15958{ /*lint --e{715}*/
15959 assert(scip != NULL);
15960 assert(conshdlr != NULL);
15962
15963 if( (*consdata)->eventdata != NULL )
15964 {
15965 SCIP_CONSHDLRDATA* conshdlrdata;
15966
15967 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15968 assert(conshdlrdata != NULL);
15969
15970 /* drop all events */
15971 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15972 assert((*consdata)->eventdata == NULL);
15973 }
15974
15975 /* free linear constraint */
15976 SCIP_CALL( consdataFree(scip, consdata) );
15977
15978 return SCIP_OKAY;
15979}
15980
15981
15982/** transforms constraint data into data belonging to the transformed problem */
15983static
15985{ /*lint --e{715}*/
15988
15989 /*debugMsg(scip, "Trans method of linear constraints\n");*/
15990
15991 assert(scip != NULL);
15992 assert(conshdlr != NULL);
15997
16000 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
16001
16002 /* create linear constraint data for target constraint */
16004
16005#ifndef NDEBUG
16006 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
16008 {
16009 int n;
16010 for(n = targetdata->nvars - 1; n >= 0; --n )
16012 }
16013#endif
16014
16015 /* create target constraint */
16021
16022 return SCIP_OKAY;
16023}
16024
16025
16026/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
16027static
16029{ /*lint --e{715}*/
16030 int c;
16031
16032 assert(scip != NULL);
16034
16035 *infeasible = FALSE;
16036
16037 for( c = 0; c < nconss && !(*infeasible); ++c )
16038 {
16039 assert(SCIPconsIsInitial(conss[c]));
16040 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
16041 }
16042
16043 return SCIP_OKAY;
16044}
16045
16046
16047/** separation method of constraint handler for LP solutions */
16048static
16050{ /*lint --e{715}*/
16051 SCIP_CONSHDLRDATA* conshdlrdata;
16052 SCIP_Real loclowerbound;
16053 SCIP_Real glblowerbound;
16054 SCIP_Real cutoffbound;
16055 SCIP_Real maxbound;
16056 SCIP_Bool separatecards;
16057 SCIP_Bool cutoff;
16058 int c;
16059 int depth;
16060 int nrounds;
16061 int maxsepacuts;
16062 int ncuts;
16063
16064 assert(scip != NULL);
16065 assert(conshdlr != NULL);
16067 assert(result != NULL);
16068
16069 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16070 assert(conshdlrdata != NULL);
16073
16074 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16075
16077
16078 /* only call the separator a given number of times at each node */
16079 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16080 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16081 return SCIP_OKAY;
16082
16083 /* get the maximal number of cuts allowed in a separation round */
16084 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16085
16086 /* check if we want to produce knapsack cardinality cuts at this node */
16089 cutoffbound = SCIPgetCutoffbound(scip);
16090 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16093
16095 ncuts = 0;
16096 cutoff = FALSE;
16097
16098 /* check all useful linear constraints for feasibility */
16099 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16100 {
16101 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16102 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16103 }
16104
16105 /* adjust return value */
16106 if( cutoff )
16108 else if( ncuts > 0 )
16110
16111 /* combine linear constraints to get more cuts */
16112 /**@todo further cuts of linear constraints */
16113
16114 return SCIP_OKAY;
16115}
16116
16117
16118/** separation method of constraint handler for arbitrary primal solutions */
16119static
16121{ /*lint --e{715}*/
16122 SCIP_CONSHDLRDATA* conshdlrdata;
16123 int c;
16124 int depth;
16125 int nrounds;
16126 int maxsepacuts;
16127 int ncuts;
16128 SCIP_Bool cutoff;
16129
16130 assert(scip != NULL);
16131 assert(conshdlr != NULL);
16133 assert(result != NULL);
16134
16135 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16136 assert(conshdlrdata != NULL);
16139
16140 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16141
16143
16144 /* only call the separator a given number of times at each node */
16145 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16146 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16147 return SCIP_OKAY;
16148
16149 /* get the maximal number of cuts allowed in a separation round */
16150 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16151
16153 ncuts = 0;
16154 cutoff = FALSE;
16155
16156 /* check all useful linear constraints for feasibility */
16157 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16158 {
16159 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16160 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16161 }
16162
16163 /* adjust return value */
16164 if( cutoff )
16166 else if( ncuts > 0 )
16168
16169 /* combine linear constraints to get more cuts */
16170 /**@todo further cuts of linear constraints */
16171
16172 return SCIP_OKAY;
16173}
16174
16175
16176/** constraint enforcing method of constraint handler for LP solutions */
16177static
16179{ /*lint --e{715}*/
16180 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16181
16182 return SCIP_OKAY;
16183}
16184
16185/** constraint enforcing method of constraint handler for relaxation solutions */
16186static
16188{ /*lint --e{715}*/
16189 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16190
16191 return SCIP_OKAY;
16192}
16193
16194/** constraint enforcing method of constraint handler for pseudo solutions */
16195static
16197{ /*lint --e{715}*/
16198 SCIP_CONSHDLRDATA* conshdlrdata;
16199 SCIP_Bool checkrelmaxabs;
16200 SCIP_Bool violated;
16201 int c;
16202
16203 assert(scip != NULL);
16204 assert(conshdlr != NULL);
16206 assert(result != NULL);
16207
16208 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16209 assert(conshdlrdata != NULL);
16210
16211 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16212
16213 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16214
16215 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16216 if( objinfeasible )
16217 {
16218 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16219
16221 return SCIP_OKAY;
16222 }
16223
16224 /* check all linear constraints for feasibility */
16225 violated = FALSE;
16226 for( c = 0; c < nconss && !violated; ++c )
16227 {
16228 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16229 }
16230
16231 if( violated )
16233 else
16235
16236 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16237
16238 return SCIP_OKAY;
16239}
16240
16241
16242/** feasibility check method of constraint handler for integral solutions */
16243static
16245{ /*lint --e{715}*/
16246 SCIP_CONSHDLRDATA* conshdlrdata;
16247 SCIP_Bool checkrelmaxabs;
16248 int c;
16249
16250 assert(scip != NULL);
16251 assert(conshdlr != NULL);
16253 assert(result != NULL);
16254
16256
16257 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16258 assert(conshdlrdata != NULL);
16259
16260 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16261
16262 /*debugMsg(scip, "Check method of linear constraints\n");*/
16263
16264 /* check all linear constraints for feasibility */
16265 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16266 {
16267 SCIP_Bool violated = FALSE;
16268 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16269
16270 if( violated )
16271 {
16273
16274 if( printreason )
16275 {
16276 SCIP_CONSDATA* consdata;
16277 SCIP_Real activity;
16278
16279 consdata = SCIPconsGetData(conss[c]);
16280 assert( consdata != NULL);
16281
16282 activity = consdataGetActivity(scip, consdata, sol);
16283
16284 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16285 SCIPinfoMessage(scip, NULL, ";\n");
16286
16287 if( activity == SCIP_INVALID ) /*lint !e777*/
16288 SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16289 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16290 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16291 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16292 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16293 }
16294 }
16295 }
16296
16297 return SCIP_OKAY;
16298}
16299
16300
16301/** domain propagation method of constraint handler */
16302static
16304{ /*lint --e{715}*/
16305 SCIP_CONSHDLRDATA* conshdlrdata;
16306 SCIP_Bool rangedrowpropagation = FALSE;
16307 SCIP_Bool tightenbounds;
16308 SCIP_Bool cutoff;
16309
16310 int nchgbds;
16311 int i;
16312
16313 assert(scip != NULL);
16314 assert(conshdlr != NULL);
16316 assert(result != NULL);
16317
16318 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16319 assert(conshdlrdata != NULL);
16320
16321 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16322
16323 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16324 if( SCIPinProbing(scip) )
16325 tightenbounds = TRUE;
16326 else
16327 {
16328 int depth;
16329 int propfreq;
16330 int tightenboundsfreq;
16331 int rangedrowfreq;
16332
16334 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16335 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16336 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16337 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16338
16339 /* check if we want to do ranged row propagation */
16340 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16341 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16342 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16343 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16344 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16345 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16346 }
16347
16348 cutoff = FALSE;
16349 nchgbds = 0;
16350
16351 /* process constraints marked for propagation */
16352 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16353 {
16355 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16356 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16357 }
16358
16359 /* adjust result code */
16360 if( cutoff )
16362 else if( nchgbds > 0 )
16364 else
16366
16367 return SCIP_OKAY;
16368}
16369
16370
16371#define MAXCONSPRESOLROUNDS 10
16372/** presolving method of constraint handler */
16373static
16375{ /*lint --e{715}*/
16376 SCIP_CONSHDLRDATA* conshdlrdata;
16377 SCIP_CONS* cons;
16378 SCIP_CONSDATA* consdata;
16379 SCIP_Real minactivity;
16380 SCIP_Real maxactivity;
16381 SCIP_Bool minactisrelax;
16382 SCIP_Bool maxactisrelax;
16383 SCIP_Bool isminsettoinfinity;
16384 SCIP_Bool ismaxsettoinfinity;
16385 SCIP_Bool cutoff;
16386 int oldnfixedvars;
16387 int oldnaggrvars;
16388 int oldnchgbds;
16389 int oldndelconss;
16390 int oldnupgdconss;
16391 int oldnchgcoefs;
16392 int oldnchgsides;
16393 int firstchange;
16394 int firstupgradetry;
16395 int c;
16396
16397 assert(scip != NULL);
16398 assert(conshdlr != NULL);
16400 assert(result != NULL);
16401
16402 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16403
16404 /* remember old preprocessing counters */
16405 cutoff = FALSE;
16406 oldnfixedvars = *nfixedvars;
16407 oldnaggrvars = *naggrvars;
16408 oldnchgbds = *nchgbds;
16409 oldndelconss = *ndelconss;
16410 oldnupgdconss = *nupgdconss;
16411 oldnchgcoefs = *nchgcoefs;
16412 oldnchgsides = *nchgsides;
16413
16414 /* get constraint handler data */
16415 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16416 assert(conshdlrdata != NULL);
16417
16418 /* process single constraints */
16421 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16422 {
16423 int npresolrounds;
16424 SCIP_Bool infeasible;
16425
16426 infeasible = FALSE;
16427
16428 cons = conss[c];
16429 assert(SCIPconsIsActive(cons));
16430 consdata = SCIPconsGetData(cons);
16431 assert(consdata != NULL);
16432
16433 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16434 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16435 {
16436 consdata->lhs = consdata->rhs;
16437 assert(consdata->row == NULL);
16438 }
16439
16440 if( consdata->eventdata == NULL )
16441 {
16442 /* catch bound change events of variables */
16443 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16444 assert(consdata->eventdata != NULL);
16445 }
16446
16447 /* constraint should not be already presolved in the initial round */
16449 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16450 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16451 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16452
16453 /* incorporate fixings and aggregations in constraint */
16454 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16455
16456 if( infeasible )
16457 {
16458 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16459 cutoff = TRUE;
16460 break;
16461 }
16462
16463 assert(consdata->removedfixings);
16464
16465 /* we can only presolve linear constraints, that are not modifiable */
16466 if( SCIPconsIsModifiable(cons) )
16467 continue;
16468
16469 /* remember the first changed constraint to begin the next aggregation round with */
16470 if( firstchange == INT_MAX && consdata->changed )
16471 firstchange = c;
16472
16473 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16474 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16476
16477 /* check, if constraint is already preprocessed */
16478 if( consdata->presolved )
16479 continue;
16480
16481 assert(SCIPconsIsActive(cons));
16482
16483 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16485
16486 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16487 * to avoid nearly infinite cycling due to very small bound changes)
16488 */
16489 npresolrounds = 0;
16490 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16491 {
16492 assert(!cutoff);
16493 npresolrounds++;
16494
16495 /* mark constraint being presolved and propagated */
16496 consdata->presolved = TRUE;
16498
16499 /* normalize constraint */
16500 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16501
16502 if( infeasible )
16503 {
16504 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16505 cutoff = TRUE;
16506 break;
16507 }
16508
16509 /* tighten left and right hand side due to integrality */
16510 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16511
16512 if( infeasible )
16513 {
16514 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16515 cutoff = TRUE;
16516 break;
16517 }
16518
16519 /* check bounds */
16520 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16521 {
16522 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16523 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16524 cutoff = TRUE;
16525 break;
16526 }
16527
16528 /* tighten variable's bounds */
16529 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16530 if( cutoff )
16531 break;
16532
16533 /* check for fixed variables */
16534 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16535 if( cutoff )
16536 break;
16537
16538 /* check constraint for infeasibility and redundancy */
16539 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
16541 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16542 {
16543 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16544 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16545 cutoff = TRUE;
16546 break;
16547 }
16548 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16549 {
16550 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16551 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16552 SCIP_CALL( SCIPdelCons(scip, cons) );
16553 assert(!SCIPconsIsActive(cons));
16554
16555 if( !consdata->upgraded )
16556 (*ndelconss)++;
16557 break;
16558 }
16559 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16560 {
16561 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16562 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16563 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16564 if( !consdata->upgraded )
16565 (*nchgsides)++;
16566 }
16567 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16568 {
16569 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16570 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16572 if( !consdata->upgraded )
16573 (*nchgsides)++;
16574 }
16575
16576 /* handle empty constraint */
16577 if( consdata->nvars == 0 )
16578 {
16579 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16580 {
16581 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16582 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16583 cutoff = TRUE;
16584 }
16585 else
16586 {
16587 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16588 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16589 SCIP_CALL( SCIPdelCons(scip, cons) );
16590 assert(!SCIPconsIsActive(cons));
16591
16592 if( !consdata->upgraded )
16593 (*ndelconss)++;
16594 }
16595 break;
16596 }
16597
16598 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16599 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16600
16601 /* try to simplify inequalities */
16602 if( conshdlrdata->simplifyinequalities )
16603 {
16604 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16605
16606 if( cutoff )
16607 break;
16608 }
16609
16610 /* aggregation variable in equations */
16611 if( conshdlrdata->aggregatevariables )
16612 {
16613 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16614 if( cutoff )
16615 break;
16616 }
16617 }
16618
16619 if( !cutoff && !SCIPisStopped(scip) )
16620 {
16621 /* perform ranged row propagation */
16622 if( conshdlrdata->rangedrowpropagation )
16623 {
16624 int lastnfixedvars;
16625
16626 lastnfixedvars = *nfixedvars;
16627
16628 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16629 if( !cutoff )
16630 {
16631 if( lastnfixedvars < *nfixedvars )
16632 {
16633 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16634 }
16635 }
16636 }
16637
16638 /* extract cliques from constraint */
16639 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16640 {
16641 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16642 nfixedvars, nchgbds, &cutoff) );
16643
16644 /* check if the constraint got redundant or infeasible */
16645 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16646 {
16647 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16648 {
16649 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16650 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16651 cutoff = TRUE;
16652 }
16653 else
16654 {
16655 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16656 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16657 SCIP_CALL( SCIPdelCons(scip, cons) );
16658 assert(!SCIPconsIsActive(cons));
16659
16660 if( !consdata->upgraded )
16661 (*ndelconss)++;
16662 }
16663 }
16664 }
16665
16666 /* convert special equalities */
16667 if( !cutoff && SCIPconsIsActive(cons) )
16668 {
16669 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16670 }
16671
16672 /* apply dual presolving for variables that appear in only one constraint */
16673 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16674 {
16675 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16676 }
16677
16678 /* check if an inequality is parallel to the objective function */
16679 if( !cutoff && SCIPconsIsActive(cons) )
16680 {
16681 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16682 }
16683
16684 /* remember the first changed constraint to begin the next aggregation round with */
16685 if( firstchange == INT_MAX && consdata->changed )
16686 firstchange = c;
16687
16688 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16689 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16691 }
16692
16693 /* singleton column stuffing */
16694 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16695 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16696 {
16697 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16698 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16699
16700 /* handle empty constraint */
16701 if( consdata->nvars == 0 )
16702 {
16703 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16704 {
16705 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16706 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16707 cutoff = TRUE;
16708 }
16709 else
16710 {
16711 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16712 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16713 SCIP_CALL( SCIPdelCons(scip, cons) );
16714 assert(!SCIPconsIsActive(cons));
16715
16716 if( !consdata->upgraded )
16717 (*ndelconss)++;
16718 }
16719 break;
16720 }
16721 }
16722 }
16723
16724 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16725 * only apply this expensive procedure in exhaustive presolving timing
16726 */
16727 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16728 {
16729 assert(firstchange >= 0);
16730
16731 if( firstchange < nconss && conshdlrdata->presolusehashing )
16732 {
16733 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16735 ndelconss, nchgsides) );
16736 }
16737
16738 if( firstchange < nconss && conshdlrdata->presolpairwise )
16739 {
16741 int nusefulconss;
16742 int firstchangenew;
16743 SCIP_Longint npaircomparisons;
16744
16745 npaircomparisons = 0;
16746 oldndelconss = *ndelconss;
16747 oldnchgsides = *nchgsides;
16748 oldnchgcoefs = *nchgcoefs;
16749
16750 /* allocate temporary memory */
16752
16753 nusefulconss = 0;
16754 firstchangenew = -1;
16755 for( c = 0; c < nconss; ++c )
16756 {
16757 /* update firstchange */
16758 if( c == firstchange )
16760
16761 /* ignore inactive and modifiable constraints */
16762 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16763 continue;
16764
16765 usefulconss[nusefulconss] = conss[c];
16766 ++nusefulconss;
16767 }
16770
16771 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16772 {
16773 /* constraint has become inactive or modifiable during pairwise presolving */
16774 if( usefulconss[c] == NULL )
16775 continue;
16776
16777 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16778
16780 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16781 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16782
16783 if( npaircomparisons > conshdlrdata->nmincomparisons )
16784 {
16786 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16787 break;
16788 oldndelconss = *ndelconss;
16789 oldnchgsides = *nchgsides;
16790 oldnchgcoefs = *nchgcoefs;
16791 npaircomparisons = 0;
16792 }
16793 }
16794 /* free temporary memory */
16796 }
16797 }
16798
16799 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16800 * in linear constraints and we therefore have full information about it
16801 */
16802 if( !cutoff && firstupgradetry < nconss
16803 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16804 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16805 )
16806 {
16807 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16808 {
16809 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16810 }
16811 }
16812
16813 /* try to upgrade constraints into a more specific constraint type;
16814 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16815 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16816 */
16817 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16818 {
16819 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16820 {
16821 cons = conss[c];
16822
16823 /* don't upgrade modifiable constraints */
16824 if( SCIPconsIsModifiable(cons) )
16825 continue;
16826
16827 consdata = SCIPconsGetData(cons);
16828 assert(consdata != NULL);
16829
16830 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16831 if( consdata->upgradetried )
16832 continue;
16833 /* @todo force that upgrade will be performed later? */
16834 if( !consdata->presolved )
16835 continue;
16836
16837 consdata->upgradetried = TRUE;
16838 if( SCIPconsIsActive(cons) )
16839 {
16841
16843 if( upgdcons != NULL )
16844 {
16845 /* add the upgraded constraint to the problem */
16848 (*nupgdconss)++;
16849
16850 /* mark the linear constraint being upgraded and to be removed after presolving;
16851 * don't delete it directly, because it may help to preprocess other linear constraints
16852 */
16853 assert(!consdata->upgraded);
16854 consdata->upgraded = TRUE;
16855
16856 /* delete upgraded inequalities immediately;
16857 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16858 */
16859 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16860 || !conshdlrdata->presolpairwise
16861 || (conshdlrdata->maxaggrnormscale == 0.0) )
16862 {
16863 SCIP_CALL( SCIPdelCons(scip, cons) );
16864 }
16865 }
16866 }
16867 }
16868 }
16869
16870 /* return the correct result code */
16871 if( cutoff )
16873 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16874 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16876 else
16878
16879 return SCIP_OKAY;
16880}
16881
16882
16883/** propagation conflict resolving method of constraint handler */
16884static
16886{ /*lint --e{715}*/
16887 assert(scip != NULL);
16888 assert(cons != NULL);
16889 assert(result != NULL);
16890
16891 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16892
16893 return SCIP_OKAY;
16894}
16895
16896
16897/** variable rounding lock method of constraint handler */
16898static
16900{ /*lint --e{715}*/
16901 SCIP_CONSDATA* consdata;
16902 SCIP_Bool haslhs;
16903 SCIP_Bool hasrhs;
16904 int i;
16905
16906 assert(scip != NULL);
16907 assert(cons != NULL);
16908 consdata = SCIPconsGetData(cons);
16909 assert(consdata != NULL);
16910
16911 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16912 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16913
16914 /* update rounding locks of every single variable */
16915 for( i = 0; i < consdata->nvars; ++i )
16916 {
16917 if( SCIPisPositive(scip, consdata->vals[i]) )
16918 {
16919 if( haslhs )
16920 {
16921 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16922 }
16923 if( hasrhs )
16924 {
16925 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16926 }
16927 }
16928 else
16929 {
16930 if( haslhs )
16931 {
16932 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16933 }
16934 if( hasrhs )
16935 {
16936 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16937 }
16938 }
16939 }
16940
16941 return SCIP_OKAY;
16942}
16943
16944
16945/** variable deletion method of constraint handler */
16946static
16948{
16949 assert(scip != NULL);
16950 assert(conshdlr != NULL);
16951 assert(conss != NULL || nconss == 0);
16952
16953 if( nconss > 0 )
16954 {
16955 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16956 }
16957
16958 return SCIP_OKAY;
16959}
16960
16961/** constraint display method of constraint handler */
16962static
16964{ /*lint --e{715}*/
16965 assert(scip != NULL);
16966 assert(conshdlr != NULL);
16967 assert(cons != NULL);
16968
16970
16971 return SCIP_OKAY;
16972}
16973
16974/** constraint copying method of constraint handler */
16975static
16977{ /*lint --e{715}*/
16979 SCIP_Real* sourcecoefs;
16980 const char* consname;
16981 int nvars;
16982
16983 assert(scip != NULL);
16984 assert(sourcescip != NULL);
16986
16987 /* get variables and coefficients of the source constraint */
16990 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16991
16992 if( name != NULL )
16993 consname = name;
16994 else
16995 consname = SCIPconsGetName(sourcecons);
16996
16997 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16998 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16999 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
17000 assert(cons != NULL || *valid == FALSE);
17001
17002 /* @todo should also the checkabsolute flag of the constraint be copied? */
17003
17004 return SCIP_OKAY;
17005}
17006
17007/** find operators '<=', '==', '>=', [free] in input string and return those places
17008 *
17009 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
17010 */
17011static
17013 const char* str, /**< null terminated input string */
17014 char** firstoperator, /**< pointer to store the string starting at the first operator */
17015 char** secondoperator, /**< pointer to store the string starting at the second operator */
17016 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
17017 )
17018{
17019 char* curr;
17020
17021 assert(str != NULL);
17024
17027
17028 curr = (char*)str;
17029 *success = TRUE;
17030
17031 /* loop over the input string to find all operators */
17032 while( *curr && *success )
17033 {
17034 SCIP_Bool found = FALSE;
17035 int increment = 1;
17036
17037 /* try if we found a possible operator */
17038 switch( *curr )
17039 {
17040 case '<':
17041 case '=':
17042 case '>':
17043
17044 /* check if the two characters curr[0,1] form an operator together */
17045 if( curr[1] == '=' )
17046 {
17047 found = TRUE;
17048
17049 /* update increment to continue after this operator */
17050 increment = 2;
17051 }
17052 break;
17053 case '[':
17054 if( strncmp(curr, "[free]", 6) == 0 )
17055 {
17056 found = TRUE;
17057
17058 /* update increment to continue after this operator */
17059 increment = 6;
17060 }
17061 break;
17062 default:
17063 break;
17064 }
17065
17066 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
17067 if( found )
17068 {
17069 if( *firstoperator == NULL )
17070 {
17071 *firstoperator = curr;
17072 }
17073 else
17074 {
17075 if( *secondoperator != NULL )
17076 {
17077 SCIPerrorMessage("Found more than two operators in line %s\n", str);
17078 *success = FALSE;
17079 }
17080 else if( strncmp(*firstoperator, "<=", 2) != 0 )
17081 {
17082 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17083 *success = FALSE;
17084 }
17085 else if( strncmp(curr, "<=", 2) != 0 )
17086 {
17087 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17088 *success = FALSE;
17089 }
17090
17091 *secondoperator = curr;
17092 }
17093 }
17094
17095 curr += increment;
17096 }
17097
17098 /* check if we did find at least one operator */
17099 if( *success )
17100 {
17101 if( *firstoperator == NULL )
17102 {
17103 SCIPerrorMessage("Could not find any operator in line %s\n", str);
17104 *success = FALSE;
17105 }
17106 }
17107}
17108
17109/** constraint parsing method of constraint handler */
17110static
17112{ /*lint --e{715}*/
17113 SCIP_VAR** vars;
17114 SCIP_Real* coefs;
17115 int nvars;
17116 int coefssize;
17117 int requsize;
17118 SCIP_Real lhs;
17119 SCIP_Real rhs;
17120 char* endptr;
17121 char* firstop;
17122 char* secondop;
17123 SCIP_Bool operatorsuccess;
17124 char* lhsstrptr;
17125 char* rhsstrptr;
17126 char* varstrptr;
17127
17128 assert(scip != NULL);
17129 assert(success != NULL);
17130 assert(str != NULL);
17131 assert(name != NULL);
17132 assert(cons != NULL);
17133
17134 /* set left and right hand side to their default values */
17135 lhs = -SCIPinfinity(scip);
17136 rhs = SCIPinfinity(scip);
17137
17138 (*success) = FALSE;
17139
17140 /* return of string empty */
17141 if( !*str )
17142 return SCIP_OKAY;
17143
17144 /* ignore whitespace */
17145 SCIP_CALL( SCIPskipSpace((char**)&str) );
17146
17147 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17148 * and the special word [free]
17149 */
17151
17152 /* if the grammar is not valid for parsing a linear constraint, return */
17153 if( ! operatorsuccess )
17154 return SCIP_OKAY;
17155
17156 varstrptr = (char *)str;
17158 assert(firstop != NULL);
17159
17160 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17161 switch( *firstop )
17162 {
17163 case '<':
17164 assert(firstop[1] == '=');
17165 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17166 if( secondop != NULL )
17167 {
17168 assert(secondop[0] == '<' && secondop[1] == '=');
17169 lhsstrptr = (char *)str;
17170 varstrptr = firstop + 2;
17171 rhsstrptr = secondop + 2;
17172 }
17173 else
17174 {
17175 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17176 lhsstrptr = NULL;
17177 varstrptr = (char *)str;
17178 rhsstrptr = firstop + 2;
17179 }
17180 break;
17181 case '>':
17182 assert(firstop[1] == '=');
17183 assert(secondop == NULL);
17184 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17185 lhsstrptr = firstop + 2;
17186 break;
17187 case '=':
17188 assert(firstop[1] == '=');
17189 assert(secondop == NULL);
17190 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17191 rhsstrptr = firstop + 2;
17192 lhsstrptr = firstop + 2;
17193 break;
17194 case '[':
17195 assert(strncmp(firstop, "[free]", 6) == 0);
17196 assert(secondop == NULL);
17197 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17198 break;
17199 default:
17200 /* it should not be possible that a different character appears in that position */
17201 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17202 return SCIP_READERROR;
17203 }
17204
17205 /* parse left hand side, if necessary */
17206 if( lhsstrptr != NULL )
17207 {
17208 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17209 {
17210 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17211 return SCIP_OKAY;
17212 }
17213
17214 /* in case of an equation, assign the left also to the right hand side */
17215 if( rhsstrptr == lhsstrptr )
17216 rhs = lhs;
17217 }
17218
17219 /* parse right hand side, if different from left hand side */
17220 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17221 {
17222 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17223 {
17224 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17225 return SCIP_OKAY;
17226 }
17227 }
17228
17229 /* initialize buffers for storing the variables and coefficients */
17230 coefssize = 100;
17231 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17232 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17233
17234 assert(varstrptr != NULL);
17235
17236 /* parse linear sum to get variables and coefficients */
17238
17239 if( *success && requsize > coefssize )
17240 {
17241 /* realloc buffers and try again */
17242 coefssize = requsize;
17243 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17244 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17245
17247 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17248 }
17249
17250 if( !*success )
17251 {
17252 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17253 }
17254 else
17255 {
17256 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17257 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17258 }
17259
17260 SCIPfreeBufferArray(scip, &coefs);
17262
17263 return SCIP_OKAY;
17264}
17265
17266
17267/** constraint method of constraint handler which returns the variables (if possible) */
17268static
17270{ /*lint --e{715}*/
17271 SCIP_CONSDATA* consdata;
17272
17273 consdata = SCIPconsGetData(cons);
17274 assert(consdata != NULL);
17275
17277 (*success) = FALSE;
17278 else
17279 {
17280 assert(vars != NULL);
17281
17282 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17283 (*success) = TRUE;
17284 }
17285
17286 return SCIP_OKAY;
17287}
17288
17289/**! [Callback for the number of variables]*/
17290/** constraint method of constraint handler which returns the number of variables (if possible) */
17291static
17293{ /*lint --e{715}*/
17294 SCIP_CONSDATA* consdata;
17295
17296 consdata = SCIPconsGetData(cons);
17297 assert(consdata != NULL);
17298
17299 (*nvars) = consdata->nvars;
17300 (*success) = TRUE;
17301
17302 return SCIP_OKAY;
17303}
17304/**! [Callback for the number of variables]*/
17305
17306/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17307static
17309{ /*lint --e{715}*/
17311
17312 return SCIP_OKAY;
17313}
17314
17315/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17316static
17323
17324/*
17325 * Callback methods of event handler
17326 */
17327
17328/** execution method of event handler */
17329static
17331{ /*lint --e{715}*/
17332 SCIP_CONS* cons;
17333 SCIP_CONSDATA* consdata;
17334 SCIP_VAR* var;
17335 SCIP_EVENTTYPE eventtype;
17336
17337 assert(scip != NULL);
17338 assert(eventhdlr != NULL);
17339 assert(eventdata != NULL);
17341 assert(event != NULL);
17342
17343 cons = eventdata->cons;
17344 assert(cons != NULL);
17345 consdata = SCIPconsGetData(cons);
17346 assert(consdata != NULL);
17347
17348 /* we can skip events droped for deleted constraints */
17349 if( SCIPconsIsDeleted(cons) )
17350 return SCIP_OKAY;
17351
17352 eventtype = SCIPeventGetType(event);
17354
17355 if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17356 {
17357 SCIP_Real oldbound;
17358 SCIP_Real newbound;
17359 SCIP_Real val;
17360 int varpos;
17361
17362 varpos = eventdata->varpos;
17363 assert(0 <= varpos && varpos < consdata->nvars);
17364 oldbound = SCIPeventGetOldbound(event);
17365 newbound = SCIPeventGetNewbound(event);
17366 assert(var != NULL);
17367 assert(consdata->vars[varpos] == var);
17368 val = consdata->vals[varpos];
17369
17370 /* we only need to update the activities if the constraint is active,
17371 * otherwise we mark them to be invalid
17372 */
17373 if( SCIPconsIsActive(cons) )
17374 {
17375 /* update the activity values */
17376 if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17377 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17378 else
17379 {
17380 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17381 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17382 }
17383 }
17384 else
17386
17387 consdata->presolved = FALSE;
17388 consdata->rangedrowpropagated = 0;
17389
17390 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17391 if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17392 {
17394
17395 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17396 if( consdata->maxactdeltavar == var )
17397 {
17398 consdata->maxactdelta = SCIP_INVALID;
17399 consdata->maxactdeltavar = NULL;
17400 }
17401
17402 /* check whether bound tightening might now be successful */
17403 if( consdata->boundstightened > 0)
17404 {
17405 switch( eventtype )
17406 {
17408 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17409 consdata->boundstightened = 0;
17410 break;
17412 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17413 consdata->boundstightened = 0;
17414 break;
17415 default:
17416 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17417 return SCIP_INVALIDDATA;
17418 }
17419 }
17420 }
17421 /* update maximal activity delta if a bound was relaxed */
17422 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17423 {
17424 SCIP_Real lb;
17425 SCIP_Real ub;
17426 SCIP_Real domain;
17427 SCIP_Real delta;
17428
17429 assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17430
17431 lb = SCIPvarGetLbLocal(var);
17432 ub = SCIPvarGetUbLocal(var);
17433
17434 domain = ub - lb;
17435 delta = REALABS(val) * domain;
17436
17437 if( delta > consdata->maxactdelta )
17438 {
17439 consdata->maxactdelta = delta;
17440 consdata->maxactdeltavar = var;
17441 }
17442 }
17443 }
17444 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17445 {
17446 /* we want to remove the fixed variable */
17447 consdata->presolved = FALSE;
17448 consdata->removedfixings = FALSE;
17449 consdata->rangedrowpropagated = 0;
17450
17451 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17452 if( consdata->maxactdeltavar == var )
17453 {
17454 consdata->maxactdelta = SCIP_INVALID;
17455 consdata->maxactdeltavar = NULL;
17456 }
17457 }
17458 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17459 {
17460 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17463 consdata->presolved = FALSE;
17464 }
17465 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17466 {
17467 SCIP_Real oldbound;
17468 SCIP_Real newbound;
17469 SCIP_Real val;
17470 int varpos;
17471
17472 varpos = eventdata->varpos;
17473 assert(0 <= varpos && varpos < consdata->nvars);
17474 oldbound = SCIPeventGetOldbound(event);
17475 newbound = SCIPeventGetNewbound(event);
17476 assert(var != NULL);
17477 assert(consdata->vars[varpos] == var);
17478 val = consdata->vals[varpos];
17479
17480 consdata->rangedrowpropagated = 0;
17481
17482 /* update the activity values */
17483 if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17484 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17485 else
17486 {
17487 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17488 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17489 }
17490
17491 /* if the variable is binary but not fixed it had to become binary due to this global change */
17493 {
17495 consdata->indexsorted = FALSE;
17496 else
17497 consdata->coefsorted = FALSE;
17498 }
17499 }
17500 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17501 {
17503
17504 /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17505 consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17506
17507 /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17508 consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17509 }
17510 else
17511 {
17512 assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17513 consdata->varsdeleted = TRUE;
17514 }
17515
17516 return SCIP_OKAY;
17517}
17518
17519
17520/*
17521 * Callback methods of conflict handler
17522 */
17523
17524/** conflict processing method of conflict handler (called when conflict was found) */
17525static
17527{ /*lint --e{715}*/
17528 SCIP_VAR** vars;
17529 SCIP_Real* vals;
17530 SCIP_Real lhs;
17531 int i;
17532
17533 assert(scip != NULL);
17536 assert(bdchginfos != NULL || nbdchginfos == 0);
17537 assert(result != NULL);
17538
17539 /* don't process already resolved conflicts */
17540 if( resolved )
17541 {
17543 return SCIP_OKAY;
17544 }
17545
17547
17548 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17549 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17550 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17551 lhs = 1.0;
17552 for( i = 0; i < nbdchginfos; ++i )
17553 {
17554 assert(bdchginfos != NULL);
17555
17556 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17557
17558 /* we can only treat binary variables */
17559 /**@todo extend linear conflict constraints to some non-binary cases */
17560 if( !SCIPvarIsBinary(vars[i]) )
17561 break;
17562
17563 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17564 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17565 vals[i] = 1.0;
17566 else
17567 {
17568 vals[i] = -1.0;
17569 lhs -= 1.0;
17570 }
17571 }
17572
17573 if( i == nbdchginfos )
17574 {
17575 SCIP_CONS* cons;
17577 char consname[SCIP_MAXSTRLEN];
17578
17579 /* create a constraint out of the conflict set */
17581 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17582 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17583
17584 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17586 if( upgdcons != NULL )
17587 {
17588 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17589 cons = upgdcons;
17590 }
17591
17592 /* add conflict to SCIP */
17594
17596 }
17597
17598 /* free temporary memory */
17599 SCIPfreeBufferArray(scip, &vals);
17601
17602 return SCIP_OKAY;
17603}
17604
17605
17606/*
17607 * Nonlinear constraint upgrading
17608 */
17609
17610/** tries to upgrade a nonlinear constraint into a linear constraint */
17611static
17613{
17614 SCIP_CONSDATA* consdata;
17615 SCIP_EXPR* expr;
17616 SCIP_Real lhs;
17617 SCIP_Real rhs;
17618 int i;
17619
17620 assert(nupgdconss != NULL);
17621 assert(upgdconss != NULL);
17622 assert(upgdconsssize > 0);
17623
17624 expr = SCIPgetExprNonlinear(cons);
17625 assert(expr != NULL);
17626
17627 /* not a linear constraint if the expression is not a sum
17628 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17629 */
17630 if( !SCIPisExprSum(scip, expr) )
17631 return SCIP_OKAY;
17632
17633 /* if at least one child is not a variable, then not a linear constraint */
17634 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17635 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17636 return SCIP_OKAY;
17637
17638 /* consider constant part of the sum expression */
17641
17643 0, NULL, NULL, lhs, rhs,
17647 SCIPconsIsStickingAtNode(cons)) );
17648 assert(upgdconss[0] != NULL);
17649
17650 consdata = SCIPconsGetData(upgdconss[0]);
17651
17652 /* add linear terms */
17654 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17655 {
17657 }
17658
17659 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17660 consdata->checkabsolute = TRUE;
17661
17662 *nupgdconss = 1;
17663
17664 SCIPdebugMsg(scip, "created linear constraint:\n");
17666
17667 return SCIP_OKAY;
17668} /*lint !e715*/
17669
17670/*
17671 * constraint specific interface methods
17672 */
17673
17674/** creates the handler for linear constraints and includes it in SCIP */
17676 SCIP* scip /**< SCIP data structure */
17677 )
17678{
17679 SCIP_CONSHDLRDATA* conshdlrdata;
17680 SCIP_CONSHDLR* conshdlr;
17681 SCIP_EVENTHDLR* eventhdlr;
17683
17684 assert(scip != NULL);
17685
17686 /* create event handler for bound change events */
17689
17690 /* create conflict handler for linear constraints */
17693
17694 /* create constraint handler data */
17695 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17696
17697 /* include constraint handler */
17701 conshdlrdata) );
17702
17703 assert(conshdlr != NULL);
17704
17705 /* set non-fundamental callbacks via specific setter functions */
17732
17733 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17734 {
17735 /* include the linear constraint upgrade in the nonlinear constraint handler */
17737 }
17738
17739 /* add linear constraint handler parameters */
17741 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17742 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17743 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17745 "constraints/" CONSHDLR_NAME "/maxrounds",
17746 "maximal number of separation rounds per node (-1: unlimited)",
17747 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17749 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17750 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17751 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17753 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17754 "maximal number of cuts separated per separation round",
17755 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17757 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17758 "maximal number of cuts separated per separation round in the root node",
17759 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17761 "constraints/" CONSHDLR_NAME "/presolpairwise",
17762 "should pairwise constraint comparison be performed in presolving?",
17763 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17765 "constraints/" CONSHDLR_NAME "/presolusehashing",
17766 "should hash table be used for detecting redundant constraints in advance",
17767 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17769 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17770 "number for minimal pairwise presolve comparisons",
17771 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17773 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17774 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17775 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17777 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17778 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17779 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17781 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17782 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17783 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17785 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17786 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17787 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17789 "constraints/" CONSHDLR_NAME "/separateall",
17790 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17791 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17793 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17794 "should presolving search for aggregations in equations",
17795 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17797 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17798 "should presolving try to simplify inequalities",
17799 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17801 "constraints/" CONSHDLR_NAME "/dualpresolving",
17802 "should dual presolving steps be performed?",
17803 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17805 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17806 "should stuffing of singleton continuous variables be performed?",
17807 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17809 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17810 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17811 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17813 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17814 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17816 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17817 "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)?",
17818 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17820 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17821 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17822 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17824 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17825 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17826 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17828 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17829 "should presolving try to detect subsets of constraints parallel to the objective function?",
17830 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17832 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17833 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17834 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17836 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17837 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17838 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17840 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17841 "maximum depth to apply ranged row propagation",
17842 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17844 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17845 "frequency for applying ranged row propagation",
17846 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17848 "constraints/" CONSHDLR_NAME "/multaggrremove",
17849 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17850 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17852 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17853 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17854 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17856 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17857 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17858 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17860 "constraints/" CONSHDLR_NAME "/extractcliques",
17861 "should Cliques be extracted?",
17862 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17863
17864 return SCIP_OKAY;
17865}
17866
17867/** includes a linear constraint update method into the linear constraint handler */
17869 SCIP* scip, /**< SCIP data structure */
17870 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17871 int priority, /**< priority of upgrading method */
17872 const char* conshdlrname /**< name of the constraint handler */
17873 )
17874{
17875 SCIP_CONSHDLR* conshdlr;
17876 SCIP_CONSHDLRDATA* conshdlrdata;
17880
17881 assert(scip != NULL);
17884
17885 /* find the linear constraint handler */
17886 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17887 if( conshdlr == NULL )
17888 {
17889 SCIPerrorMessage("linear constraint handler not found\n");
17890 return SCIP_PLUGINNOTFOUND;
17891 }
17892
17893 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17894 assert(conshdlrdata != NULL);
17895
17896 /* check if linear constraint update method already exists in constraint handler data */
17897 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17898 {
17899 /* create a linear constraint upgrade data object */
17901
17902 /* insert linear constraint update method into constraint handler data */
17904
17905 /* adds parameter to turn on and off the upgrading step */
17906 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17907 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17910 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17911 }
17912
17913 return SCIP_OKAY;
17914}
17915
17916/** creates and captures a linear constraint
17917 *
17918 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17919 */
17921 SCIP* scip, /**< SCIP data structure */
17922 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17923 const char* name, /**< name of constraint */
17924 int nvars, /**< number of nonzeros in the constraint */
17925 SCIP_VAR** vars, /**< array with variables of constraint entries */
17926 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17927 SCIP_Real lhs, /**< left hand side of constraint */
17928 SCIP_Real rhs, /**< right hand side of constraint */
17929 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17930 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17931 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17932 * Usually set to TRUE. */
17933 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17934 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17935 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17936 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17937 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17938 * Usually set to TRUE. */
17939 SCIP_Bool local, /**< is constraint only valid locally?
17940 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17941 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17942 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17943 * adds coefficients to this constraint. */
17944 SCIP_Bool dynamic, /**< is constraint subject to aging?
17945 * Usually set to FALSE. Set to TRUE for own cuts which
17946 * are separated as constraints. */
17947 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17948 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17949 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17950 * if it may be moved to a more global node?
17951 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17952 )
17953{
17954 SCIP_CONSHDLR* conshdlr;
17955 SCIP_CONSDATA* consdata;
17956 int j;
17957
17958 assert(scip != NULL);
17959 assert(cons != NULL);
17960
17961 /* find the linear constraint handler */
17962 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17963 if( conshdlr == NULL )
17964 {
17965 SCIPerrorMessage("linear constraint handler not found\n");
17966 return SCIP_PLUGINNOTFOUND;
17967 }
17968
17969 for( j = 0; j < nvars; ++j )
17970 {
17971 if( SCIPisInfinity(scip, REALABS(vals[j])) )
17972 {
17973 SCIPerrorMessage("coefficient of variable <%s> is infinite.\n", SCIPvarGetName(vars[j]));
17974 SCIPABORT();
17975 return SCIP_INVALIDDATA;
17976 }
17977 }
17978
17979 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17980 * constraint after presolving we have to ensure that it holds active variables
17981 */
17983 {
17984 SCIP_VAR** consvars;
17985 SCIP_Real* consvals;
17986 SCIP_Real constant = 0.0;
17987 int nconsvars;
17988 int requiredsize;
17989
17990 nconsvars = nvars;
17991 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17992 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17993
17994 /* get active variables for new constraint */
17995 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17996
17997 /* if space was not enough we need to resize the buffers */
17998 if( requiredsize > nconsvars )
17999 {
18002
18003 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18004 assert(requiredsize <= nconsvars);
18005 }
18006
18007 /* adjust sides and check that we do not subtract infinity values */
18008 if( SCIPisInfinity(scip, REALABS(constant)) )
18009 {
18010 if( constant < 0.0 )
18011 {
18012 if( SCIPisInfinity(scip, lhs) )
18013 {
18015 SCIPfreeBufferArray(scip, &consvars);
18016
18017 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);
18018
18019 SCIPABORT();
18020 return SCIP_INVALIDDATA; /*lint !e527*/
18021 }
18022 if( SCIPisInfinity(scip, rhs) )
18023 {
18025 SCIPfreeBufferArray(scip, &consvars);
18026
18027 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);
18028
18029 SCIPABORT();
18030 return SCIP_INVALIDDATA; /*lint !e527*/
18031 }
18032
18033 lhs = -SCIPinfinity(scip);
18034 rhs = -SCIPinfinity(scip);
18035 }
18036 else
18037 {
18038 if( SCIPisInfinity(scip, -lhs) )
18039 {
18041 SCIPfreeBufferArray(scip, &consvars);
18042
18043 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);
18044
18045 SCIPABORT();
18046 return SCIP_INVALIDDATA; /*lint !e527*/
18047 }
18048 if( SCIPisInfinity(scip, -rhs) )
18049 {
18051 SCIPfreeBufferArray(scip, &consvars);
18052
18053 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);
18054
18055 SCIPABORT();
18056 return SCIP_INVALIDDATA; /*lint !e527*/
18057 }
18058
18059 lhs = SCIPinfinity(scip);
18060 rhs = SCIPinfinity(scip);
18061 }
18062 }
18063 else
18064 {
18065 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18066 lhs -= constant;
18067 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18068 rhs -= constant;
18069
18070 if( SCIPisInfinity(scip, -lhs) )
18071 lhs = -SCIPinfinity(scip);
18072 else if( SCIPisInfinity(scip, lhs) )
18073 lhs = SCIPinfinity(scip);
18074
18075 if( SCIPisInfinity(scip, rhs) )
18076 rhs = SCIPinfinity(scip);
18077 else if( SCIPisInfinity(scip, -rhs) )
18078 rhs = -SCIPinfinity(scip);
18079 }
18080
18081 /* create constraint data */
18082 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
18083 assert(consdata != NULL);
18084
18086 SCIPfreeBufferArray(scip, &consvars);
18087 }
18088 else
18089 {
18090 /* create constraint data */
18091 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18092 assert(consdata != NULL);
18093 }
18094
18095#ifndef NDEBUG
18096 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18097 if( check || enforce )
18098 {
18099 int n;
18100 for(n = consdata->nvars - 1; n >= 0; --n )
18101 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18102 }
18103#endif
18104
18105 /* create constraint */
18106 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18107 local, modifiable, dynamic, removable, stickingatnode) );
18108
18109 return SCIP_OKAY;
18110}
18111
18112/** creates and captures a linear constraint
18113 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18114 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18115 *
18116 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18117 *
18118 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18119 */
18121 SCIP* scip, /**< SCIP data structure */
18122 SCIP_CONS** cons, /**< pointer to hold the created constraint */
18123 const char* name, /**< name of constraint */
18124 int nvars, /**< number of nonzeros in the constraint */
18125 SCIP_VAR** vars, /**< array with variables of constraint entries */
18126 SCIP_Real* vals, /**< array with coefficients of constraint entries */
18127 SCIP_Real lhs, /**< left hand side of constraint */
18128 SCIP_Real rhs /**< right hand side of constraint */
18129 )
18130{
18131 assert(scip != NULL);
18132
18133 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18135
18136 return SCIP_OKAY;
18137}
18138
18139/** creates by copying and captures a linear constraint */
18141 SCIP* scip, /**< target SCIP data structure */
18142 SCIP_CONS** cons, /**< pointer to store the created target constraint */
18143 SCIP* sourcescip, /**< source SCIP data structure */
18144 const char* name, /**< name of constraint */
18145 int nvars, /**< number of variables in source variable array */
18146 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18147 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18148 SCIP_Real lhs, /**< left hand side of the linear constraint */
18149 SCIP_Real rhs, /**< right hand side of the linear constraint */
18150 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18151 * variables of the target SCIP */
18152 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18153 * target constraints */
18154 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18155 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18156 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18157 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18158 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18159 SCIP_Bool local, /**< is constraint only valid locally? */
18160 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18161 SCIP_Bool dynamic, /**< is constraint subject to aging? */
18162 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18163 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18164 * if it may be moved to a more global node? */
18165 SCIP_Bool global, /**< create a global or a local copy? */
18166 SCIP_Bool* valid /**< pointer to store if the copying was valid */
18167 )
18168{
18169 SCIP_VAR** vars;
18170 SCIP_Real* coefs;
18171
18172 SCIP_Real constant;
18173 int requiredsize;
18174 int v;
18175 SCIP_Bool success;
18176
18177 if( SCIPisGT(scip, lhs, rhs) )
18178 {
18179 *valid = FALSE;
18180 return SCIP_OKAY;
18181 }
18182
18183 (*valid) = TRUE;
18184
18185 if( nvars == 0 )
18186 {
18187 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18188 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18189 return SCIP_OKAY;
18190 }
18191
18192 /* duplicate variable array */
18194
18195 /* duplicate coefficient array */
18196 if( sourcecoefs != NULL )
18197 {
18199 }
18200 else
18201 {
18203 for( v = 0; v < nvars; ++v )
18204 coefs[v] = 1.0;
18205 }
18206
18207 constant = 0.0;
18208
18209 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18210 * the target SCIP
18211 */
18212 if( !SCIPvarIsOriginal(vars[0]) )
18213 {
18214 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18215
18216 if( requiredsize > nvars )
18217 {
18220
18221 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18223 }
18224 }
18225 else
18226 {
18227 for( v = 0; v < nvars; ++v )
18228 {
18230 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18231 assert(vars[v] != NULL);
18232 }
18233 }
18234
18235 success = TRUE;
18236 /* map variables of the source constraint to variables of the target SCIP */
18237 for( v = 0; v < nvars && success; ++v )
18238 {
18239 SCIP_VAR* var;
18240 var = vars[v];
18241
18242 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18243 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18244
18245 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18246 assert(!(success) || vars[v] != NULL);
18247 }
18248
18249 /* only create the target constraint, if all variables could be copied */
18250 if( success )
18251 {
18252 if( !SCIPisInfinity(scip, -lhs) )
18253 lhs -= constant;
18254
18255 if( !SCIPisInfinity(scip, rhs) )
18256 rhs -= constant;
18257
18258 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18259 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18260 }
18261 else
18262 *valid = FALSE;
18263
18264 /* free buffer array */
18265 SCIPfreeBufferArray(scip, &coefs);
18267
18268 return SCIP_OKAY;
18269}
18270
18271/** adds coefficient to linear constraint (if it is not zero) */
18273 SCIP* scip, /**< SCIP data structure */
18274 SCIP_CONS* cons, /**< constraint data */
18275 SCIP_VAR* var, /**< variable of constraint entry */
18276 SCIP_Real val /**< coefficient of constraint entry */
18277 )
18278{
18279 assert(scip != NULL);
18280 assert(cons != NULL);
18281 assert(var != NULL);
18282
18284 {
18285 SCIPerrorMessage("constraint is not linear\n");
18286 return SCIP_INVALIDDATA;
18287 }
18288
18289 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18290 * constraint after presolving we have to ensure that it holds active variables
18291 */
18293 {
18294 SCIP_CONSDATA* consdata;
18295 SCIP_VAR** consvars;
18296 SCIP_Real* consvals;
18297 SCIP_Real constant = 0.0;
18298 SCIP_Real rhs;
18299 SCIP_Real lhs;
18300 int nconsvars;
18301 int requiredsize;
18302 int v;
18303
18304 nconsvars = 1;
18305 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18307 consvars[0] = var;
18308 consvals[0] = val;
18309
18310 /* get active variables for new constraint */
18311 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18312
18313 /* if space was not enough we need to resize the buffers */
18314 if( requiredsize > nconsvars )
18315 {
18318
18319 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18320 assert(requiredsize <= nconsvars);
18321 }
18322
18323 consdata = SCIPconsGetData(cons);
18324 assert(consdata != NULL);
18325
18326 lhs = consdata->lhs;
18327 rhs = consdata->rhs;
18328
18329 /* adjust sides and check that we do not subtract infinity values */
18330 /* constant is infinite */
18331 if( SCIPisInfinity(scip, REALABS(constant)) )
18332 {
18333 if( constant < 0.0 )
18334 {
18335 if( SCIPisInfinity(scip, lhs) )
18336 {
18338 SCIPfreeBufferArray(scip, &consvars);
18339
18340 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));
18341
18342 SCIPABORT();
18343 return SCIP_INVALIDDATA; /*lint !e527*/
18344 }
18345 if( SCIPisInfinity(scip, rhs) )
18346 {
18348 SCIPfreeBufferArray(scip, &consvars);
18349
18350 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));
18351
18352 SCIPABORT();
18353 return SCIP_INVALIDDATA; /*lint !e527*/
18354 }
18355
18356 lhs = -SCIPinfinity(scip);
18357 rhs = -SCIPinfinity(scip);
18358 }
18359 else
18360 {
18361 if( SCIPisInfinity(scip, -lhs) )
18362 {
18364 SCIPfreeBufferArray(scip, &consvars);
18365
18366 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));
18367
18368 SCIPABORT();
18369 return SCIP_INVALIDDATA; /*lint !e527*/
18370 }
18371 if( SCIPisInfinity(scip, -rhs) )
18372 {
18374 SCIPfreeBufferArray(scip, &consvars);
18375
18376 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));
18377
18378 SCIPABORT();
18379 return SCIP_INVALIDDATA; /*lint !e527*/
18380 }
18381
18382 lhs = SCIPinfinity(scip);
18383 rhs = SCIPinfinity(scip);
18384 }
18385 }
18386 /* constant is not infinite */
18387 else
18388 {
18389 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18390 lhs -= constant;
18391 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18392 rhs -= constant;
18393
18394 if( SCIPisInfinity(scip, -lhs) )
18395 lhs = -SCIPinfinity(scip);
18396 else if( SCIPisInfinity(scip, lhs) )
18397 lhs = SCIPinfinity(scip);
18398
18399 if( SCIPisInfinity(scip, rhs) )
18400 rhs = SCIPinfinity(scip);
18401 else if( SCIPisInfinity(scip, -rhs) )
18402 rhs = -SCIPinfinity(scip);
18403 }
18404
18405 /* add all active variables to constraint */
18406 for( v = nconsvars - 1; v >= 0; --v )
18407 {
18408 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18409 }
18410
18411 /* update left and right hand sides */
18412 SCIP_CALL( chgLhs(scip, cons, lhs));
18413 SCIP_CALL( chgRhs(scip, cons, rhs));
18414
18416 SCIPfreeBufferArray(scip, &consvars);
18417 }
18418 else
18419 {
18420 SCIP_CALL( addCoef(scip, cons, var, val) );
18421 }
18422
18423 return SCIP_OKAY;
18424}
18425
18426/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18427 * not yet contained in the constraint
18428 *
18429 * @note This method may only be called during problem creation stage for an original constraint and variable.
18430 *
18431 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18432 */
18434 SCIP* scip, /**< SCIP data structure */
18435 SCIP_CONS* cons, /**< constraint data */
18436 SCIP_VAR* var, /**< variable of constraint entry */
18437 SCIP_Real val /**< new coefficient of constraint entry */
18438 )
18439{
18440 SCIP_CONSDATA* consdata;
18441 SCIP_VAR** vars;
18442 SCIP_Bool found;
18443 int i;
18444
18445 assert(scip != NULL);
18446 assert(cons != NULL);
18447 assert(var != NULL);
18448
18450 {
18451 SCIPerrorMessage("constraint is not linear\n");
18452 return SCIP_INVALIDDATA;
18453 }
18454
18456 {
18457 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18458 return SCIP_INVALIDDATA;
18459 }
18460
18461 consdata = SCIPconsGetData(cons);
18462 assert(consdata != NULL);
18463
18464 vars = consdata->vars;
18465 found = FALSE;
18466 i = 0;
18467 while( i < consdata->nvars )
18468 {
18469 if( vars[i] == var )
18470 {
18471 if( found || SCIPisZero(scip, val) )
18472 {
18473 SCIP_CALL( delCoefPos(scip, cons, i) );
18474
18475 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18476 i--;
18477 }
18478 else
18479 {
18480 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18481 }
18482 found = TRUE;
18483 }
18484 i++;
18485 }
18486
18487 if( !found && !SCIPisZero(scip, val) )
18488 {
18489 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18490 }
18491
18492 return SCIP_OKAY;
18493}
18494
18495/** deletes variable from linear constraint
18496 *
18497 * @note This method may only be called during problem creation stage for an original constraint and variable.
18498 *
18499 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18500 */
18502 SCIP* scip, /**< SCIP data structure */
18503 SCIP_CONS* cons, /**< constraint data */
18504 SCIP_VAR* var /**< variable of constraint entry */
18505 )
18506{
18507 assert(scip != NULL);
18508 assert(cons != NULL);
18509 assert(var != NULL);
18510
18511 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18512
18513 return SCIP_OKAY;
18514}
18515
18516/** gets left hand side of linear constraint */
18518 SCIP* scip, /**< SCIP data structure */
18519 SCIP_CONS* cons /**< constraint data */
18520 )
18521{
18522 SCIP_CONSDATA* consdata;
18523
18524 assert(scip != NULL);
18525 assert(cons != NULL);
18526
18528 {
18529 SCIPerrorMessage("constraint is not linear\n");
18530 SCIPABORT();
18531 return SCIP_INVALID; /*lint !e527*/
18532 }
18533
18534 consdata = SCIPconsGetData(cons);
18535 assert(consdata != NULL);
18536
18537 return consdata->lhs;
18538}
18539
18540/** gets right hand side of linear constraint */
18542 SCIP* scip, /**< SCIP data structure */
18543 SCIP_CONS* cons /**< constraint data */
18544 )
18545{
18546 SCIP_CONSDATA* consdata;
18547
18548 assert(scip != NULL);
18549 assert(cons != NULL);
18550
18552 {
18553 SCIPerrorMessage("constraint is not linear\n");
18554 SCIPABORT();
18555 return SCIP_INVALID; /*lint !e527*/
18556 }
18557
18558 consdata = SCIPconsGetData(cons);
18559 assert(consdata != NULL);
18560
18561 return consdata->rhs;
18562}
18563
18564/** changes left hand side of linear constraint */
18566 SCIP* scip, /**< SCIP data structure */
18567 SCIP_CONS* cons, /**< constraint data */
18568 SCIP_Real lhs /**< new left hand side */
18569 )
18570{
18571 assert(scip != NULL);
18572 assert(cons != NULL);
18573
18575 {
18576 SCIPerrorMessage("constraint is not linear\n");
18577 return SCIP_INVALIDDATA;
18578 }
18579
18580 SCIP_CALL( chgLhs(scip, cons, lhs) );
18581
18582 return SCIP_OKAY;
18583}
18584
18585/** changes right hand side of linear constraint */
18587 SCIP* scip, /**< SCIP data structure */
18588 SCIP_CONS* cons, /**< constraint data */
18589 SCIP_Real rhs /**< new right hand side */
18590 )
18591{
18593 {
18594 SCIPerrorMessage("constraint is not linear\n");
18595 return SCIP_INVALIDDATA;
18596 }
18597
18598 SCIP_CALL( chgRhs(scip, cons, rhs) );
18599
18600 return SCIP_OKAY;
18601}
18602
18603/** gets the number of variables in the linear constraint */
18605 SCIP* scip, /**< SCIP data structure */
18606 SCIP_CONS* cons /**< constraint data */
18607 )
18608{
18609 SCIP_CONSDATA* consdata;
18610
18611 assert(scip != NULL);
18612 assert(cons != NULL);
18613
18615 {
18616 SCIPerrorMessage("constraint is not linear\n");
18617 SCIPABORT();
18618 return -1; /*lint !e527*/
18619 }
18620
18621 consdata = SCIPconsGetData(cons);
18622 assert(consdata != NULL);
18623
18624 return consdata->nvars;
18625}
18626
18627/** gets the array of variables in the linear constraint; the user must not modify this array! */
18629 SCIP* scip, /**< SCIP data structure */
18630 SCIP_CONS* cons /**< constraint data */
18631 )
18632{
18633 SCIP_CONSDATA* consdata;
18634
18635 assert(scip != NULL);
18636 assert(cons != NULL);
18637
18639 {
18640 SCIPerrorMessage("constraint is not linear\n");
18641 SCIPABORT();
18642 return NULL; /*lint !e527*/
18643 }
18644
18645 consdata = SCIPconsGetData(cons);
18646 assert(consdata != NULL);
18647
18648 return consdata->vars;
18649}
18650
18651/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18653 SCIP* scip, /**< SCIP data structure */
18654 SCIP_CONS* cons /**< constraint data */
18655 )
18656{
18657 SCIP_CONSDATA* consdata;
18658
18659 assert(scip != NULL);
18660 assert(cons != NULL);
18661
18663 {
18664 SCIPerrorMessage("constraint is not linear\n");
18665 SCIPABORT();
18666 return NULL; /*lint !e527*/
18667 }
18668
18669 consdata = SCIPconsGetData(cons);
18670 assert(consdata != NULL);
18671
18672 return consdata->vals;
18673}
18674
18675/** gets the activity of the linear constraint in the given solution
18676 *
18677 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18678 * comprises positive and negative infinity contributions
18679 */
18681 SCIP* scip, /**< SCIP data structure */
18682 SCIP_CONS* cons, /**< constraint data */
18683 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18684 )
18685{
18686 SCIP_CONSDATA* consdata;
18687
18688 assert(scip != NULL);
18689 assert(cons != NULL);
18690
18692 {
18693 SCIPerrorMessage("constraint is not linear\n");
18694 SCIPABORT();
18695 return SCIP_INVALID; /*lint !e527*/
18696 }
18697
18698 consdata = SCIPconsGetData(cons);
18699 assert(consdata != NULL);
18700
18701 if( consdata->row != NULL )
18702 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18703 else
18704 return consdataGetActivity(scip, consdata, sol);
18705}
18706
18707/** gets the feasibility of the linear constraint in the given solution */
18709 SCIP* scip, /**< SCIP data structure */
18710 SCIP_CONS* cons, /**< constraint data */
18711 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18712 )
18713{
18714 SCIP_CONSDATA* consdata;
18715
18716 assert(scip != NULL);
18717 assert(cons != NULL);
18718
18720 {
18721 SCIPerrorMessage("constraint is not linear\n");
18722 SCIPABORT();
18723 return SCIP_INVALID; /*lint !e527*/
18724 }
18725
18726 consdata = SCIPconsGetData(cons);
18727 assert(consdata != NULL);
18728
18729 if( consdata->row != NULL )
18730 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18731 else
18732 return consdataGetFeasibility(scip, consdata, sol);
18733}
18734
18735/** gets the dual solution of the linear constraint in the current LP */
18737 SCIP* scip, /**< SCIP data structure */
18738 SCIP_CONS* cons /**< constraint data */
18739 )
18740{
18741 SCIP_CONSDATA* consdata;
18742
18743 assert(scip != NULL);
18744 assert(cons != NULL);
18745 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18746
18748 {
18749 SCIPerrorMessage("constraint is not linear\n");
18750 SCIPABORT();
18751 return SCIP_INVALID; /*lint !e527*/
18752 }
18753
18754 consdata = SCIPconsGetData(cons);
18755 assert(consdata != NULL);
18756
18757 if( consdata->row != NULL )
18758 return SCIProwGetDualsol(consdata->row);
18759 else
18760 return 0.0;
18761}
18762
18763/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18765 SCIP* scip, /**< SCIP data structure */
18766 SCIP_CONS* cons /**< constraint data */
18767 )
18768{
18769 SCIP_CONSDATA* consdata;
18770
18771 assert(scip != NULL);
18772 assert(cons != NULL);
18773 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18774
18776 {
18777 SCIPerrorMessage("constraint is not linear\n");
18778 SCIPABORT();
18779 return SCIP_INVALID; /*lint !e527*/
18780 }
18781
18782 consdata = SCIPconsGetData(cons);
18783 assert(consdata != NULL);
18784
18785 if( consdata->row != NULL )
18786 return SCIProwGetDualfarkas(consdata->row);
18787 else
18788 return 0.0;
18789}
18790
18791/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18792 * the user must not modify the row!
18793 */
18795 SCIP* scip, /**< SCIP data structure */
18796 SCIP_CONS* cons /**< constraint data */
18797 )
18798{
18799 SCIP_CONSDATA* consdata;
18800
18801 assert(scip != NULL);
18802 assert(cons != NULL);
18803
18805 {
18806 SCIPerrorMessage("constraint is not linear\n");
18807 SCIPABORT();
18808 return NULL; /*lint !e527*/
18809 }
18810
18811 consdata = SCIPconsGetData(cons);
18812 assert(consdata != NULL);
18813
18814 return consdata->row;
18815}
18816
18817/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18819 SCIP* scip, /**< SCIP data structure */
18820 SCIP_CONS* cons, /**< source constraint to try to convert */
18821 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18822 )
18823{
18824 SCIP_CONSHDLR* conshdlr;
18825 SCIP_CONSHDLRDATA* conshdlrdata;
18826 SCIP_CONSDATA* consdata;
18827 SCIP_VAR* var;
18828 SCIP_Real val;
18829 SCIP_Real lb;
18830 SCIP_Real ub;
18831 SCIP_Real poscoeffsum;
18832 SCIP_Real negcoeffsum;
18833 SCIP_Bool infeasible;
18834 SCIP_Bool integral;
18835 int nchgsides = 0;
18836 int nposbin;
18837 int nnegbin;
18838 int nposint;
18839 int nnegint;
18840 int nposimpl;
18841 int nnegimpl;
18842 int nposimplbin;
18843 int nnegimplbin;
18844 int nposcont;
18845 int nnegcont;
18846 int ncoeffspone;
18847 int ncoeffsnone;
18848 int ncoeffspint;
18849 int ncoeffsnint;
18850 int ncoeffspfrac;
18851 int ncoeffsnfrac;
18852 int i;
18853
18854 assert(scip != NULL);
18855 assert(cons != NULL);
18856 assert(upgdcons != NULL);
18857
18858 *upgdcons = NULL;
18859
18860 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18861 if( SCIPconsIsModifiable(cons) )
18862 return SCIP_OKAY;
18863
18864 /* check for upgradability */
18865 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18866 return SCIP_OKAY;
18867
18868 /* get the constraint handler and check, if it's really a linear constraint */
18869 conshdlr = SCIPconsGetHdlr(cons);
18870 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18871 {
18872 SCIPerrorMessage("constraint is not linear\n");
18873 return SCIP_INVALIDDATA;
18874 }
18875
18876 /* get constraint handler data and constraint data */
18877 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18878 assert(conshdlrdata != NULL);
18879 consdata = SCIPconsGetData(cons);
18880 assert(consdata != NULL);
18881
18882 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18883 if( consdata->upgraded )
18884 return SCIP_OKAY;
18885
18886 /* check, if the constraint is already stored as LP row */
18887 if( consdata->row != NULL )
18888 {
18889 if( SCIProwIsInLP(consdata->row) )
18890 {
18891 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18892 return SCIP_INVALIDDATA;
18893 }
18894 else
18895 {
18896 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18897 }
18898 }
18899
18900 /* normalize constraint */
18901 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18902
18903 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18904 * skipped and we hope that the infeasibility gets detected later again.
18905 *
18906 * TODO: do we want to try to upgrade the constraint anyway?
18907 *
18908 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18909 * proven to be infeasible.
18910 */
18911 if( infeasible ) /*lint !e774*/
18912 return SCIP_OKAY;
18913
18914 /* tighten sides */
18915 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18916
18917 if( infeasible ) /*lint !e774*/
18918 return SCIP_OKAY;
18919
18920 /*
18921 * calculate some statistics on linear constraint
18922 */
18923
18924 nposbin = 0;
18925 nnegbin = 0;
18926 nposint = 0;
18927 nnegint = 0;
18928 nposimpl = 0;
18929 nnegimpl = 0;
18930 nposimplbin = 0;
18931 nnegimplbin = 0;
18932 nposcont = 0;
18933 nnegcont = 0;
18934 ncoeffspone = 0;
18935 ncoeffsnone = 0;
18936 ncoeffspint = 0;
18937 ncoeffsnint = 0;
18938 ncoeffspfrac = 0;
18939 ncoeffsnfrac = 0;
18940 integral = TRUE;
18941 poscoeffsum = 0.0;
18942 negcoeffsum = 0.0;
18943
18944 for( i = 0; i < consdata->nvars; ++i )
18945 {
18946 var = consdata->vars[i];
18947 val = consdata->vals[i];
18948 lb = SCIPvarGetLbLocal(var);
18949 ub = SCIPvarGetUbLocal(var);
18950 assert(!SCIPisZero(scip, val));
18951
18952 switch( SCIPvarGetType(var) )
18953 {
18955 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18956 integral = integral && SCIPisIntegral(scip, val);
18957 if( val >= 0.0 )
18958 nposbin++;
18959 else
18960 nnegbin++;
18961 break;
18963 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18964 integral = integral && SCIPisIntegral(scip, val);
18965 if( val >= 0.0 )
18966 nposint++;
18967 else
18968 nnegint++;
18969 break;
18971 if( SCIPvarIsBinary(var) )
18972 {
18973 if( val >= 0.0 )
18974 nposimplbin++;
18975 else
18976 nnegimplbin++;
18977 }
18978 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18979 integral = integral && SCIPisIntegral(scip, val);
18980 if( val >= 0.0 )
18981 nposimpl++;
18982 else
18983 nnegimpl++;
18984 break;
18986 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18987 if( val >= 0.0 )
18988 nposcont++;
18989 else
18990 nnegcont++;
18991 break;
18992 default:
18993 SCIPerrorMessage("unknown variable type\n");
18994 return SCIP_INVALIDDATA;
18995 }
18996 if( SCIPisEQ(scip, val, 1.0) )
18997 ncoeffspone++;
18998 else if( SCIPisEQ(scip, val, -1.0) )
18999 ncoeffsnone++;
19000 else if( SCIPisIntegral(scip, val) )
19001 {
19002 if( SCIPisPositive(scip, val) )
19003 ncoeffspint++;
19004 else
19005 ncoeffsnint++;
19006 }
19007 else
19008 {
19009 if( SCIPisPositive(scip, val) )
19010 ncoeffspfrac++;
19011 else
19012 ncoeffsnfrac++;
19013 }
19014 if( SCIPisPositive(scip, val) )
19015 poscoeffsum += val;
19016 else
19017 negcoeffsum += val;
19018 }
19019
19020 /*
19021 * call the upgrading methods
19022 */
19023
19024 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
19025 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
19026 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",
19029 poscoeffsum, negcoeffsum, integral);
19030
19031 /* try all upgrading methods in priority order in case the upgrading step is enable */
19032 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
19033 {
19034 if( conshdlrdata->linconsupgrades[i]->active )
19035 {
19036 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
19037 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
19040 poscoeffsum, negcoeffsum, integral,
19041 upgdcons) );
19042 }
19043 }
19044
19045#ifdef SCIP_DEBUG
19046 if( *upgdcons != NULL )
19047 {
19049 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
19051 }
19052#endif
19053
19054 return SCIP_OKAY; /*lint !e438*/
19055}
19056
19057/** cleans up (multi-)aggregations and fixings from linear constraints */
19059 SCIP* scip, /**< SCIP data structure */
19060 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
19061 SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
19062 )
19063{
19064 SCIP_CONSHDLR* conshdlr;
19065 SCIP_CONS** conss;
19066 int nconss;
19067 int i;
19068
19069 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
19070 if( conshdlr == NULL )
19071 return SCIP_OKAY;
19072
19073 assert(infeasible != NULL);
19074 *infeasible = FALSE;
19075
19077 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
19078
19079 for( i = 0; i < nconss; ++i )
19080 {
19081 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
19082
19083 if( *infeasible )
19084 break;
19085 }
19086
19087 return SCIP_OKAY;
19088}
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)
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 *isrelax, SCIP_Bool *issettoinfinity)
#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 consdataGetActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
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)
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
#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 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 void consdataGetGlbActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *glbminactivity, SCIP_Real *glbmaxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
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 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 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
#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
#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 SCIP_Bool canTightenBounds(SCIP_CONS *cons)
#define DEFAULT_SEPARATEALL
static void findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
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 *isrelax, SCIP_Bool *issettoinfinity)
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
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 *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
#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_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:1740
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:5205
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:4353
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:6923
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition scip_var.c:1482
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:8567
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:18144
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:8600
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:8403
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:5617
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:5322
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:1796
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:4261
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:4439
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2130
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:8537
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18680
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1250
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition scip_var.c:4647
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:4615
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:8178
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1695
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:6782
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:8278
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:5503
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:1994
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:4515
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:1441
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1216
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition scip_var.c:8631
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:5434
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